PHP ZipArchive 在 Windows 中损坏

2022-08-30 18:04:42

我正在使用PHP的ZipArchive类创建一个包含照片的zip文件,然后将其提供给浏览器进行下载。这是我的代码:

/**
 * Grabs the order, packages the files, and serves them up for download.
 *
 * @param string $intEntryID 
 * @return void
 * @author Jesse Bunch
 */
public static function download_order_by_entry_id($intUniqueID) {

    $objCustomer = PhotoCustomer::get_customer_by_unique_id($intUniqueID);

    if ($objCustomer):

        if (!class_exists('ZipArchive')):
            trigger_error('ZipArchive Class does not exist', E_USER_ERROR);
        endif;

        $objZip = new ZipArchive();
        $strZipFilename = sprintf('%s/application/tmp/%s-%s.zip', $_SERVER['DOCUMENT_ROOT'], $objCustomer->getEntryID(), time());

        if ($objZip->open($strZipFilename, ZIPARCHIVE::CREATE) !== TRUE):

            trigger_error('Unable to create zip archive', E_USER_ERROR);

        endif;          

        foreach($objCustomer->arrPhotosRequested as $objPhoto):

            $filename = PhotoCart::replace_ee_file_dir_in_string($objPhoto->strHighRes);
            $objZip->addFile($filename,sprintf('/press_photos/%s-%s', $objPhoto->getEntryID(), basename($filename)));

        endforeach;

        $objZip->close();

        header('Last-Modified: '.gmdate('D, d M Y H:i:s', filemtime($strZipFilename)).' GMT',  TRUE, 200);
        header('Cache-Control: no-cache', TRUE);
        header('Pragma: Public', TRUE);
        header('Expires: ' . gmdate('D, d M Y H:i:s', time()) . ' GMT', TRUE);
        header('Content-Length: '.filesize($strZipFilename), TRUE);
        header('Content-disposition: attachment; filename=press_photos.zip', TRUE);

        header('Content-Type: application/octet-stream', TRUE);

        ob_start();
        readfile($strZipFilename);
        ob_end_flush();
        exit;

    else:

        trigger_error('Invalid Customer', E_USER_ERROR);

    endif;

}

此代码适用于除 IE 之外的所有浏览器。在 IE 中,文件可以正确下载,但 zip 存档为空。尝试提取文件时,Windows告诉我zip存档已损坏。以前有人遇到过这个问题吗?

编辑更新:根据@profitphp的建议,我将标题更改为:

header("Cache-Control: public");
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: public");
//header("Content-Description: File Transfer");
//header("Content-type: application/zip");
header("Content-Disposition: attachment; filename=\"pressphotos.zip\"");
//header("Content-Transfer-Encoding: binary");
header("Content-length: " . filesize($strZipFilename));

另外,这是使用Firefox打开后Windows中错误的屏幕截图:

alt text

此错误发生在 Windows 上的 IE 和 Firefox 中。它在Mac中工作正常。此外,在 Windows 中,文件大小似乎是正确的:

alt text

编辑 #2这个问题是悬而未决的。请参阅下面的答案。


答案 1

我遇到了同样的问题,我的解决方案与此线程上的正确答案类似。将文件放入存档时,不能有绝对文件(以斜杠开头的文件),否则由于某种原因,该文件将无法在 Windows 中打开。

因此,之所以让它工作,不是因为他(Jesse Bunch,撰写本文时选择的答案)删除了包含文件夹,而是因为他删除了起始斜杠。

我通过更改来解决此问题

$zip->addFile($file, $file); // $file is something like /path/to/file.png

// we make file relative by removing beginning slash so it will open in Windows
$zip->addFile($file, ltrim($file, '/'));

然后它能够在Windows中打开!

这可能与pclzip(Plahcinski的答案)起作用的原因相同。我敢打赌它会自动剥离开头的斜杠。

如果没有 PHP 文档页面上的特定评论,我就不会弄清楚这一点。ZipArchive::addFile


答案 2

我最近遇到了一个与你描述的类似的问题。我发现ZipArchive充其量是不稳定的。

我用这个简单的库解决了我的问题

http://www.phpconcept.net/pclzip

include_once('libs/pclzip.lib.php');

...

function zip($source, $destination){
$zipfile = new PclZip($destination);
$v_list = $zipfile->create($source, '', $source); }

$source = 我要压缩的文件夹 $destination = zip 文件位置

我花了2天时间寻找ZipArchive,然后在5分钟内解决了PCLZip的所有问题。

希望这有助于您和其他任何遇到此问题的人(因为这接近该问题的顶级Google结果)。


推荐