【问题标题】:PHP Download Script Creates Unreadable ZIP File on MacPHP 下载脚本在 Mac 上创建不可读的 ZIP 文件
【发布时间】:2012-09-06 20:22:41
【问题描述】:

作为参考,我已经阅读并尝试了这些和其他几个线程中的答案:

Creating and serving zipped files with php

Opening downloaded zip file creates cpgz file?

我的服务器上有一个 zip 文件。

  1. 当我使用 Filezilla 将该 Zip 文件从我的服务器移动到我的 Mac 时,我可以正常打开它。

  2. 当我使用此 PHP 代码将 Zip 文件下载到我的 Linux 机器时,它可以正常打开。

  3. 当我使用此 PHP 代码通过 Safari 或 Firefox 将 Zip 文件下载到我的 Mac 时,我收到一条错误消息,提示“解压缩失败”或“存档结构已损坏”,或者我得到一个 . cpgz 文件 - 我相信这意味着计算机正在压缩文件,而不是解压缩它。

这是我用来传递 zip 文件的 PHP 代码。

$zipname = "myfile.zip";
$zippath = "/path/to/" . $zipname;

      if ($downloadzip = fopen ($zippath, "r")) {
            $fsize = filesize($zippath);

            header("Content-type: application/zip");
            header("Content-Disposition: attachment; filename=\"".$zipname."\"");
            header("Content-length: $fsize");
            header('Content-Transfer-Encoding: binary');
            #header("Cache-control: private"); //use this to open files directly

            echo fpassthru($downloadzip); // deliver the zip file

        }
        fclose ($downloadzip);

我发现了一些有用的标题。我真的不知道也不关心它为什么会起作用,我只是很高兴它起作用了……我尝试了很多不同的东西,.htaccess 文件,php.ini / zlib 设置。

这就是答案 http://perishablepress.com/http-headers-file-downloads/

$zipName = 'myfile.zip';
$zipPath = 'mydirectory/' . $zipName;


    if (file_exists($zipPath)) {

        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/octet-stream");
        header("Content-Disposition: attachment; filename=\"".$zipName."\"");
        header("Content-Transfer-Encoding: binary");
        header("Content-Length: ".filesize($zipPath));
        ob_end_flush();
        @readfile($zipPath);
}

【问题讨论】:

  • echo fpassthru($downloadzip); 替换为readfile( $zippath ); 会发生什么?您是否尝试过删除:header('Content-Transfer-Encoding: binary');
  • 当我使用 readfile() 时,它的大小为 0.2 MB,这太小了。我已经删除了header('Content-Transfer-Encoding: binary');,但没有任何区别。

标签: php macos download zip


【解决方案1】:

此问题通常是由在您读出文件之前已打印或回显到页面的额外字符引起的。即使是空格也会导致失败。要解决该问题,请在读取将清除输出缓冲区并关闭缓冲的文件之前调用ob_end_clean();

但请记住,您可以有 嵌套 输出缓冲区,这也会损坏您的下载(感谢 Vladamir 解决这个问题)。因此,要在读取文件之前完全清除输出缓冲区:

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

这将清除您的整个缓冲区,并且您不会有任何额外的字符来搞乱您的下载。

对于那些感兴趣的人,我在下面粘贴了我的下载脚本。我的 zip 文件现在可以完美下载,到目前为止效果很好。

if (file_exists($zip_file_path)) {

        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");
        //We can likely use the 'application/zip' type, but the octet-stream 'catch all' works just fine.  
        header("Content-type: application/octet-stream");
        header("Content-Disposition: attachment; filename='$zip_file_name'");
        header("Content-Transfer-Encoding: binary");
        header("Content-Length: ".filesize($zip_file_path));

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

        @readfile($zip_file_path);

        exit;
}

【讨论】:

  • 几个小时后,您的周期解决了我的问题。清洗每个缓冲液就是解决方案。
  • 很高兴能帮上忙。它也让我陷入了一个循环,直到我在另一个站点上找到了这个解决方案。快乐编码...
  • 我已经努力了好几个小时。感谢十亿马克西姆斯!我从没想过 ob_get_level 循环会完成这项工作!谢谢!!!!
  • 谢谢!花了几个小时试图找出这个问题,这就是解决方案。干杯!
【解决方案2】:

这是有效的

$zipName = 'myfile.zip';
$zipPath = 'mydirectory/' . $zipName;

    if (file_exists($zipPath)) {

        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/octet-stream");
        header("Content-Disposition: attachment; filename=\"".$zipName."\"");
        header("Content-Transfer-Encoding: binary");
        header("Content-Length: ".filesize($zipPath));
        ob_end_flush();
        @readfile($zipPath);
}

【讨论】:

  • nice .. 我的问题在 safari 中通过在读取文件之前添加 ob_end_flush(); 解决了。想强调一下,我在 Safari 中下载 zip 文件和 .html 扩展名时遇到了问题
【解决方案3】:

好吧,我假设您知道您的 $fsize 变量没有被写入该标头,因为它被引号括起来。 你可以试试这样的:

header('Cache-Control: public');
header('Content-Description: File Transfer');
header('Content-Disposition: attachment; filename=\"".$zipname."\"');
header('Content-Type: application/zip');

【讨论】:

  • $fsize 应该可以正常工作,它被双引号包围,而不是单引号。
  • 我确实认为 $fsize 正在工作,当我注释掉该标题行时,下载不知道文件有多大。当该标题行正在使用时,下载确实知道文件有多大。
  • @Chris 我的错误。尝试将大小添加到我提供的上述标题中,看看是否可行。
  • @chriscct7 你的标题给了我同样的结果
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-09-10
  • 1970-01-01
  • 2011-02-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-21
相关资源
最近更新 更多