【问题标题】:PHP - Corrupted zip when adding zip into zipPHP - 将 zip 添加到 zip 时损坏的 zip
【发布时间】:2016-12-18 18:29:13
【问题描述】:

我目前正在开发一个用 PHP 制作的工具(使用这项技术的新手...),它应该生成包含一组文件的 zip 文件。这组文件可以是:

  • 基本文件(多种格式)
  • 完整目录(将作为新的压缩文件添加到生成的 zip - 最终 ZIP 中的 ZIP)

问题是,当 zip 文件包含简单文件时,它会正确下载,但当文件包含“完整目录 zip 文件”时,生成的 ZIP 文件会损坏......

在我当前使用的代码下方(如果有点乱,很抱歉,但这是我第一次使用 PHP...)

function ZipFiles($fileArr,$id) {
    $destination = "{$_SERVER['DOCUMENT_ROOT']}/wmdmngtools/tempFiles/WMDConfigFiles_".$id.".zip";
    $valid_files = array();

    //if files were passed in...
    if(is_array($fileArr)) {
        //cycle through each file
        foreach($fileArr as $file) {            

            if(is_dir($file)) {
                //If path is a folder we zip it and put it on $valid_files[]
                $resultingZipPath = "{$_SERVER['DOCUMENT_ROOT']}/wmdmngtools/tempFiles/".basename($file)."_FOLDER.zip";
                ZipFolder($file,$resultingZipPath );
                $valid_files[] = $resultingZipPath ;    
            }
            else {              
                //If path is not a folder then we make sure the file exists
                if(file_exists("{$_SERVER['DOCUMENT_ROOT']}/wmdmngtools/tempFiles/".$file)) {
                    $valid_files[] = $file;                 
                }
            }
        }
    }
    //if we have good files...
    if(count($valid_files)) {
        //create the archive
        $zip = new ZipArchive();
        if($zip->open($destination,ZIPARCHIVE::CREATE) !== true) {
            return false;
        }
        //add the files
        foreach($valid_files as $file) {
            $zip->addFile("{$_SERVER['DOCUMENT_ROOT']}/wmdmngtools/tempFiles/".$file,$file);
        }

        $zip->close();

        return $destination;
    }
    else
    {
        return "";
    }
}

function ZipFolder($source, $destination) {

    // Initialize archive object
    $folderZip = new ZipArchive();
    $folderZip->open($destination, ZipArchive::CREATE | ZipArchive::OVERWRITE);

    // Create recursive directory iterator
    /** @var SplFileInfo[] $files */
    $files = new RecursiveIteratorIterator(
        new RecursiveDirectoryIterator($source),
        RecursiveIteratorIterator::LEAVES_ONLY
    );

    foreach ($files as $name => $file)
    {
        // Skip directories (they would be added automatically)
        if (!$file->isDir())
        {
            // Get real and relative path for current file
            $filePath = $file->getRealPath();
            $relativePath = substr($filePath, strlen($source) + 1);

            // Add current file to archive
            $folderZip->addFile($filePath, $relativePath);
        }
    }

    // Zip archive will be created only after closing object
    $folderZip->close();

}

在上面我们可以看到两个功能:

  • ZipFiles:是通过传递列表/数组(包含将添加到最终 ZIP 中的文件和文件夹列表)和仅用于生成不同文件名的 ID 参数调用的主要功能。 .(可以忽略)
  • ZipFolder:为上述列表/数组中的每个文件夹(不是文件)调用此函数,以便压缩该文件夹并创建一个 zip 文件以将其添加到最终文件中。 (基于我在How to zip a whole folder using PHP 中找到的内容)

我已经尝试了很多类似上面帖子中提到的事情,比如关闭所有文件,或者避免在 zip 中使用空 zip,但没有任何效果......

Zip inside zip (php)

也许我错过了一些东西(很可能:))但我的王牌用完了,所以任何帮助/指导将不胜感激。

如果需要更多信息,请告诉我并发布。

提前非常感谢!!

【问题讨论】:

  • 有人知道我可能做错了什么吗? :)

标签: php zip


【解决方案1】:

终于找到问题了。似乎该文件已正确生成,但是从 PHP 下载它时,当大小大于具体数字时会出现问题。 这是由于标头定义上的消息长度定义错误:

header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Length: ".filesize($zippedFile));
header("Content-Disposition: attachment; filename=".$zippedFile);   
header("Content-type: application/zip");
header("Content-Transfer-Encoding: binary");

即使我猜这可能不是一个正确的做法,我还是删除了 Content-Length 条目,现在我得到了正确的文件,尽管它的大小。

【讨论】:

  • 太棒了,发现这个错误时遇到问题。
猜你喜欢
  • 2015-09-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-06
相关资源
最近更新 更多