将zip文件解压缩到文件夹的根目录?

时间:2011-07-13 16:44:14

标签: php zip

我将一个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,它将作为ff提取到myFolder

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

有没有办法将folder1中的文件解压缩到myFolder的根目录?

理想:

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

PS:包含冲突文件名我只需要不提取或覆盖文件。

3 个答案:

答案 0 :(得分:4)

请改用此小代码段。它删除了每个文件的文件名前面的文件夹结构,以便归档的整个内容基本上被提取到一个文件夹。

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

答案 1 :(得分: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();
}

答案 2 :(得分: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');
}

以上内容取代了for循环的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();
}
?>