PHP Zip 文件下载打开时出错

问题描述 投票:0回答:6

我需要从网站下载 zip 文件,因为我需要在一次下载中合并多个文件(最多 100 个单独的文件)

尝试创建 zip 文件时,它会按预期下载,文件名也按预期格式显示为 “YYYY.MM.DD - HH.MM.SS”。我的问题发生在尝试在 Windows 7 (或 winzip) 中打开 zip 文件时 - 我收到以下错误消息。经过多次尝试,这种情况反复发生。

我假设我在编码创建或下载 zip 文件时犯了一个错误,而不是 zip 文件格式本身是一个问题,因为我可以打开不同的 zip 文件 - 谁能看到我可能犯的错误? (错误图像下方包含代码)

我尝试使用 使用 php 将多个文件下载为 zip 文件作为参考。

//backup file name based on current date and time
$filename = date("Y.m.j - H.i.s");
//name of zip file used when downloading
$zipname = 'temp.zip';
//create new zip file
$zip = new ZipArchive;
$zip->open($zipname, ZipArchive::CREATE);
//yes, I know the zip file is empty currently - I've cut the code from here for
//now as the zip file doesn't function with / without it currently
$zip->close();

//download file from temporary file on server as '$filename.zip'
header('Content-Type: application/zip');
header('Content-disposition: attachment; filename='.$filename.'.zip');
header('Content-Length: ' . filesize($zipname));
readfile($zipname);
php file download zip
6个回答
6
投票

尝试使用文本编辑器打开 zip 文件。 这样您就可以检查代码中是否存在 php 错误(在压缩步骤期间)。


3
投票

检查 Web 服务器用户是否对您在其中创建 ZIP 文件的文件夹具有写入权限。尽管有文档,如果无法创建 ZIP 文件,

ZipArchive::open()
将默默失败并返回
true
(即成功)。此外,
ZipArchive::addFile()
似乎会向这个不存在的存档添加任意数量的文件,也不会报告错误。第一个出现错误的时刻是 ZipArchive::close() 返回“false”时。错误日志中也没有出现任何错误消息。

Readfile()
will 向日志报告错误并失败,因此结果是本地硬盘上的零长度 ZIP 文件。

原因似乎是 ZipArchive 类仅在内存中组装文件列表,直到关闭为止,此时它将所有文件组装到 Zip 文件中。如果无法完成此操作,则

ZipArchive::close()
返回
false

注意:如果zip文件为空,则可能根本无法创建!您的下载将继续进行,但

readfile()
将失败,并且您将下载一个零长度的 ZIP 文件。

该怎么办?

在代码中添加一些错误检查以报告其中的一些内容:

$zip = new ZipArchive;
$zip->open($zipname, ZipArchive::CREATE);

// Add your files here

if ($zip->close() === false) {
   exit("Error creating ZIP file");
};


//download file from temporary file on server as '$filename.zip'
if (file_exists($zipname)) {

    header('Content-Type: application/zip');
    header('Content-disposition: attachment; filename='.$filename.'.zip');
    header('Content-Length: ' . filesize($zipname));
    readfile($zipname);
} else {
    exit("Could not find Zip file to download");
}

2
投票

我遇到了这个问题,但这个解决方案为我解决了它

Add ob_clean(); just before your new output headers.

我使用的是旧版本的 Silverstripe,尽管数据明显存在,但我的 zip 文件不断损坏。

上面这个晦涩注释的解决方案是使用 ob_clean();很有帮助,我想把它作为这个问题的答案。

来自 PHP 文档:

ob_clean();
丢弃输出缓冲区的内容。

ob_clean();
不会像 ob_end_clean() 那样破坏输出缓冲区。


1
投票

尝试添加 ob_end_clean(); 在标题之前

    <?php
$zip = new ZipArchive();
$zip_name = $name.".zip"; // Zip name
$tmpFile=APPPATH.'../'.$zip_name;
$zip->open($zip_name,  ZipArchive::CREATE);
foreach ($images as $files) {
  if(!empty($files->cloudinary_img_url)){
  $zip->addFromString(basename($files->car_images),  file_get_contents(getImagesDropbox($files->cloudinary_img_url)));  
 
  }
  else{
   echo"file does not exist";
  }
}  
$zip->close();
 ob_end_clean();
header('Content-Type: application/zip');
header('Content-disposition: attachment; filename="'.$zip_name.'"');
header('Content-Length: ' . filesize($tmpFile));
readfile($tmpFile);
unlink($tmpFile);
  ?>

0
投票

就我而言,这有效

将其放在 php 文件的开头

ob_start();

然后,在标题之后和读取文件之前放置此

while (ob_get_level()) {
    ob_end_clean();
}

总结

ob_start();//this is new
//backup file name based on current date and time
$filename = date("Y.m.j - H.i.s");
//name of zip file used when downloading
$zipname = 'temp.zip';
//create new zip file
$zip = new ZipArchive;
$zip->open($zipname, ZipArchive::CREATE);
//yes, I know the zip file is empty currently - I've cut the code from here for
//now as the zip file doesn't function with / without it currently
$zip->close();

//download file from temporary file on server as '$filename.zip'
header('Content-Type: application/zip');
header('Content-disposition: attachment; filename='.$filename.'.zip');
header('Content-Length: ' . filesize($zipname));
while (ob_get_level()) {//this is new
  ob_end_clean();//this is new
}//this is new
readfile($zipname);

0
投票

$zip->close();

        ob_clean(); <-- this is the asnwer

        header('Content-Type: application/zip');
        header('Content-disposition: attachment; filename='.$nombreDir.'.zip');
        header('Content-Length: ' . filesize($directorioCreado . '.zip'));
        header('cache-control: no-cache, must-revalidate');
        header('Expires: 0');
        readfile($directorioCreado . '.zip');
© www.soinside.com 2019 - 2024. All rights reserved.