У меня есть zip-файл, загруженный на сервер для автоматического извлечения.
конструкция zip-файла выглядит так:
/zip_file.zip/folder1/image1.jpg /zip_file.zip/folder1/image2.jpg /zip_file.zip/folder1/image3.jpg
В настоящее время у меня есть эта функция для извлечения всех файлов с расширением jpg:
$zip = new ZipArchive(); if( $zip->open($file_path) ){ $files = array(); for( $i = 0; $i < $zip->numFiles; $i++){ $entry = $zip->statIndex($i); // is it an image? if( $entry['size'] > 0 && preg_match('#\.(jpg)$#i', $entry['name'] ) ){ $f_extract = $zip->getNameIndex($i); $files[] = $f_extract; } } if ($zip->extractTo($dir_name, $files) === TRUE) { } else { return FALSE; } $zip->close(); }
Но, используя функцию extractTo
, она будет извлекаться в myFolder
как ff:
/myFolder/folder1/image1.jpg /myFolder/folder1/image2.jpg /myFolder/folder1/image3.jpg
Есть ли способ извлечь файлы в папке1 в корень myFolder?
Идеально:
/myFolder/image1.jpg /myFolder/image2.jpg /myFolder/image3.jpg
PS: включить имя файла конфликта Мне нужно только не извлекать и не перезаписывать файл.
Вместо этого используйте этот небольшой фрагмент кода. Он удаляет структуру папок перед именем файла для каждого файла, так что весь контент архива в основном извлекается в одну папку.
<?php $path = "zip_file.zip"; $zip = new ZipArchive(); if ($zip->open($path) === true) { for($i = 0; $i < $zip->numFiles; $i++) { $filename = $zip->getNameIndex($i); $fileinfo = pathinfo($filename); copy("zip://".$path."#".$filename, "/myDestFolder/".$fileinfo['basename']); } $zip->close(); } ?>
Здесь: (я пытался все обойти)
$zip = new ZipArchive(); if( $zip->open($file_path) ){ $files = array(); for( $i = 0; $i < $zip->numFiles; $i++){ $entry = $zip->statIndex($i); // is it an image? if( $entry['size'] > 0 && preg_match('#\.(jpg)$#i', $entry['name'] ) ){ $f_extract = $zip->getNameIndex($i); $files[] = $f_extract; /* you man want to keep this array (use it to show result or something else) */ if ($zip->extractTo($dir_name, $f_extract) === TRUE) { $solid_name = basename($f_extract); if(strpos($f_extract, "/")) // make sure zipped file is in a directory { if($dir_name{strlen($dir_name)-1} == "/") $dir_name = substr($dir_name, 0, strlen($dir_name)-1); // to prevent error if $dir_name have slash in end of it if(!file_exists($dir_name."/".$solid_name)) // you said you don't want to replace existed file copy($dir_name."/".$f_extract, $dir_name."/".$solid_name); // taking file back to where you need [$dir_name] unlink($dir_name."/".$f_extract); // [removing old file] rmdir(str_replace($solid_name, "", $dir_name."/".$f_extract)); // [removing directory of it] } } else { echo("error on export<br />\n"); } } } $zip->close(); }
Вы можете сделать это, используя синтаксис zip://
вместо Zip::extractTo
как описано в руководстве по php для extractTo () .
Вы должны соответствовать имени файла изображения, а затем скопировать его:
if ($entry['size'] > 0 && preg_match('#\.(jpg)$#i', $entry['name'])) { copy('zip://' . $file_path . '#' . $entry['name'], '/root_dir/' . md5($entry['name']) . '.jpg'); }
extractTo
заменяет ваш оператор if if и делает ваш extractTo
ненужным. Я использовал хеш md5 исходного имени файла, чтобы создать уникальное имя. Очень маловероятно, что у вас возникнут проблемы с перезаписи файлов, так как хеш-столкновения редки. Обратите внимание, что это немного тяжелая работа, и вместо этого вы можете сделать str_replace('/.', '', $entry['name'])
чтобы создать новое уникальное имя файла.
Полное решение (измененная версия вашего кода):
<?php $zip = new ZipArchive(); if ($zip->open($file_path)) { for ($i = 0; $i < $zip->numFiles; $i++) { $entry = $zip->statIndex($i); // is it an image? if ($entry['size'] > 0 && preg_match('#\.(jpg)$#i', $entry['name'])) { # use hash (more expensive, but can be useful depending on what you're doing $new_filename = md5($entry['name']) . '.jpg'; # or str_replace for cheaper, potentially longer name: # $new_filename = str_replace('/.', '', $entry['name']); copy('zip://' . $file_path . '#' . $entry['name'], '/myFolder/' . $new_filename); } } $zip->close(); } ?>