【问题标题】:In memory download and extract zip archive在内存中下载并解压缩 zip 存档
【发布时间】:2011-11-15 13:24:10
【问题描述】:

我想下载一个 zip 存档并使用 PHP 将其解压缩到内存中。

这就是我今天所拥有的(这对我来说文件处理太多了:)):

// download the data file from the real page
copy("http://www.curriculummagic.com/AdvancedBalloons.kmz", "./data/zip.kmz");

// unzip it
$zip = new ZipArchive;
$res = $zip->open('./data/zip.kmz');
if ($res === TRUE) {
    $zip->extractTo('./data');
    $zip->close();
}

// use the unzipped files...

【问题讨论】:

    标签: php zip unzip


    【解决方案1】:

    您可以获取压缩包内文件的流并将其提取到变量中:

    $fp = $zip->getStream('test.txt');
    if(!$fp) exit("failed\n");
    
    while (!feof($fp)) {
        $contents .= fread($fp, 1024);
    }
    
    fclose($fp);
    

    【讨论】:

    • 如何下载文件并将其“通过管道”传送到$zip
    【解决方案2】:

    警告:这不能在内存中完成——ZipArchive 不能使用“内存映射文件”

    您可以使用file_get_contentsDocs 将压缩文件内的文件数据获取到变量(内存)中,因为它支持zip:// Stream wrapper Docs

    $zipFile = './data/zip.kmz';     # path of zip-file
    $fileInZip = 'test.txt';         # name the file to obtain
    
    # read the file's data:
    $path = sprintf('zip://%s#%s', $zipFile, $fileInZip);
    $fileData = file_get_contents($path);
    

    您只能使用zip:// 或通过 ZipArchive 访问本地文件。为此,您可以先将内容复制到一个临时文件并使用它:

    $zip = 'http://www.curriculummagic.com/AdvancedBalloons.kmz';
    $file = 'doc.kml';
    
    $ext = pathinfo($zip, PATHINFO_EXTENSION);
    $temp = tempnam(sys_get_temp_dir(), $ext);
    copy($zip, $temp);
    $data = file_get_contents("zip://$temp#$file");
    unlink($temp);
    

    【讨论】:

    • 不,zip:// 目前仅支持本地文件(以及 ZipArchive)。您必须通过标准文件系统访问它。将更新答案以使您的 http 网址可见。
    • 不,不支持堆叠流,我想即使file:// 也行不通。它必须是文件系统的路径。 ZipArchive 类也是如此,我认为这是相互关联的。在 zip PHP 扩展中,流并没有得到很好的支持,这在我看来有点可惜。去找临时文件来解决这个问题,第二个代码示例。您可以将其封装到它自己的扩展/装饰 ZipArchive 的类中,并提供一个文件系统包装器,使其更流畅。
    • @dacwe:如果你的文件系统挂载了一个 ramdisk,那么让ZipArchive 在内存中工作完全没有问题——重要的是:)
    • 是的,这实际上是我解决它的方式,但它不是一个 php 解决方案.. :)
    【解决方案3】:

    如果您可以使用系统调用,最简单的方法应该是这样的(bzip2 案例)。你只需使用标准输出。

    $out=shell_exec('bzip2 -dkc '.$zip);
    

    【讨论】:

      【解决方案4】:

      简单到:

      $zipFile = "test.zip";
      $fileInsideZip = "somefile.txt";
      $content = file_get_contents("zip://$zipFile#$fileInsideZip");
      

      【讨论】:

        【解决方案5】:

        老话题,但仍然相关,因为我问自己同样的问题,但没有找到答案。

        我最终编写了这个函数,它返回一个数组,其中包含存档中包含的每个文件的名称,以及该文件的解压缩内容:

        function GetZipContent(String $body_containing_zip_file) {
        
            $sectors = explode("\x50\x4b\x01\x02", $data);
            array_pop($sectors);
            $files = explode("\x50\x4b\x03\x04", implode("\x50\x4b\x01\x02", $sectors));
            array_shift($files);
        
            $result = array();
            foreach($files as $file) {
                $header = unpack("vversion/vflag/vmethod/vmodification_time/vmodification_date/Vcrc/Vcompressed_size/Vuncompressed_size/vfilename_length/vextrafield_length", $file);
                array_push($result, [
                    'filename' => substr($file, 26, $header['filename_length']),
                    'content' => gzinflate(substr($file, 26 + $header['filename_length'], -12))
                ]);
            }
            
            return $result;
        }
        

        希望这有用...

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-01-31
          • 2015-06-16
          • 2013-02-27
          • 1970-01-01
          相关资源
          最近更新 更多