2011-07-13 4 views
2

У меня есть 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?

Ideal:

/myFolder/image1.jpg 
/myFolder/image2.jpg 
/myFolder/image3.jpg 

PS: упаковывают имя файла конфликта нужно только не извлекать или перезаписать файл.

ответ

3

Используйте этот небольшой фрагмент кода вместо этого. Он удаляет структуру папок перед именем файла для каждого файла, так что весь контент архива в основном извлекается в одну папку.

<?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();     
} 
?> 
+5

Это решение будет перезаписывать файлы с одинаковыми именами в разных подкаталогах. – shelhamer

+0

Спасибо @Fabianius –

+0

Спасибо, что здесь http://php.net/manual/en/ziparchive.extractto.php#100802, но приземлился здесь, пытаясь понять, где находится ресурс, который показывает, что такое 'zip: //' protocol есть, у кого-нибудь есть ссылка для этого? – blamb

0

Здесь: (я пытался управлять всем)

$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(); 
} 
0

Вы можете сделать это, используя синтаксис zip:// вместо Zip::extractTo, как описано в php manual on extractTo().

Вы должны совпадать с именем файла изображения, а затем скопировать его:

if ($entry['size'] > 0 && preg_match('#\.(jpg)$#i', $entry['name'])) { 
    copy('zip://' . $file_path . '#' . $entry['name'], '/root_dir/' . md5($entry['name']) . '.jpg'); 
} 

выше заменяет для цикла выполняется, если заявление и делает 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(); 
} 
?> 
+0

Это, безусловно, лучшее решение для проверки дубликатов. Однако зачем использовать хэш-алгоритм для уникальности имен файлов? Хеширование каждого файла занимает много времени, если в архиве ZIP есть много файлов. В любом случае, решение, которое сохраняет исходное имя файла, является предпочтительным. Например, вы можете добавить последовательный номер в скобки к файлам с одинаковым именем файла. – Fabianius

+0

Последовательный номер может создавать сами дубликаты, если кто-то назвал файлы с последовательными номерами в конце :). Однако вы правы в том, что хеширование может быть чрезмерным, поэтому я предоставил альтернативу, превратив путь в имя файла с помощью 'str_replace' – shelhamer

Смежные вопросы