1

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

使用 php 创建和提供压缩文件

打开下载的 zip 文件会创建 cpgz 文件吗?

我的服务器上有一个 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);
}
4

3 回答 3

8

通常问题是由在您读出文件之前打印或回显到页面的额外字符引起的。即使是空格也会导致失败。要解决该问题,请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;
}
于 2015-08-12T20:28:18.693 回答
5

这是有效的

$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);
}
于 2012-09-13T23:29:53.313 回答
0

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

header('Cache-Control: public');
header('Content-Description: File Transfer');
header('Content-Disposition: attachment; filename=\"".$zipname."\"');
header('Content-Type: application/zip');
于 2012-09-13T17:24:42.537 回答