PHP ZipArchive在Windows中损坏

Jes*_*nch 19 php windows ziparchive

我使用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;

}
Run Code Online (Sandbox Code Playgroud)

此代码适用于除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));
Run Code Online (Sandbox Code Playgroud)

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

替代文字

Windows上的IE和Firefox都会出现此错误.它在Mac上运行良好.此外,在Windows中,filesize似乎是正确的:

替代文字

编辑#2此问题已被解决.请参阅下面的答案.

CWS*_*ear 24

我有同样的问题,我的解决方案类似于这个线程的正确答案.当您将文件放入存档时,您不能拥有绝对文件(以斜杠开头的文件),否则由于某种原因它将无法在Windows中打开.

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

我通过改变来解决这个问题

$zip->addFile($file, $file); // $file is something like /path/to/file.png
Run Code Online (Sandbox Code Playgroud)

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

然后它就能在Windows中打开!

这可能与pclzip(Plahcinski的回答)有效的原因相同.我打赌它会自动剥离开始的斜线.

如果没有对PHP 文档页面的特别评论,我就不会想到这一点ZipArchive::addFile.

  • 这对我来说是个问题,帮助很大 (2认同)

小智 14

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

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

http://www.phpconcept.net/pclzip

include_once('libs/pclzip.lib.php');
Run Code Online (Sandbox Code Playgroud)

...

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

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

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

希望这可以帮助您和其他任何有此问题的人(因为这个问题接近谷歌的最高结果).


Luc*_*llo 9

所有这些建议都可以帮到你,但在我的情况下我需要写一个ob_clean(); 在第一个标题之前(''); 因为我打印的一些文件在打印一些破坏了Windows上的zip文件的字符之前.

$zip=new ZipArchive();
$zip->open($filename, ZIPARCHIVE::CREATE);
$zip->addFile($file_to_attach,$real_file_name_to_attach);
$zip->close();

ob_clean();
header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past
header('Content-Type: application/x-download');
header('Content-Disposition: attachment; filename="file.zip"');
readfile($filename);
exit;
Run Code Online (Sandbox Code Playgroud)


Jes*_*nch 6

好吧,经过多次冲突,我发现了问题.问题来自以下代码行:

$objZip->addFile($filename,sprintf('/press_photos/%s-%s', $objPhoto->getEntryID(), basename($filename)));
Run Code Online (Sandbox Code Playgroud)

出于某种原因,/press_photos/zip存档中本地(内部)文件名的路径部分导致Windows认为zip文件已损坏.修改行后看起来如下所示,Windows正确打开了zip文件.唷.

$objZip->addFile($filename,sprintf('%s-%s', $objPhoto->getEntryID(), basename($filename)));
Run Code Online (Sandbox Code Playgroud)

  • 添加到存档后,我成功重命名了文件.如果您不需要在存档中维护目录结构,这是一个很好的解决方案:$ zip-> addFile($ uri,basename($ uri)); $ zip-> renameName(basename($ uri),str_replace('_',' - ',basename($ uri))); (3认同)

小智 5

使用特殊字符(如下划线)会导致问题,因为ZipArchive需要IBM850编码的条目名称.请参阅在线PHP手册中的注释:http://www.php.net/manual/en/function.ziparchive-addfile.php#95725.