简体   繁体   English

PHP下载脚本在Mac上创建了无法读取的ZIP文件

[英]PHP Download Script Creates Unreadable ZIP File on Mac

For reference, I have already read and tried the answers in these and several other threads: 作为参考,我已经阅读并尝试了这些和其他几个线程的答案:

Creating and serving zipped files with php 使用php创建和提供压缩文件

Opening downloaded zip file creates cpgz file? 打开下载的zip文件会创建cpgz文件吗?

I have a zip file on my server. 我的服务器上有一个zip文件。

  1. When I use Filezilla to move that Zip file from my server to my Mac, I can open it normally. 当我使用Filezilla将那个Zip文件从服务器移动到Mac时,可以正常打开它。

  2. When I use this PHP code to download the Zip file to my Linux machine, it opens normally. 当我使用此PHP代码将Zip文件下载到我的Linux机器时,它将正常打开。

  3. When I use this PHP code to download the Zip file to my Mac, using Safari or Firefox, I get an error saying "Decompression Failed" or "The structure of the archive is damaged" or I get a .cpgz file - which I believe means that the computer is zipping the file, not unzipping it. 当我使用此PHP代码通过Safari或Firefox将Zip文件下载到Mac时,出现错误消息,提示“解压缩失败”或“档案的结构已损坏”,或者得到了.cpgz文件-我相信表示计算机正在压缩文件,而不是解压缩文件。

Here is the PHP code I am using to deliver the zip file. 这是我用来传递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);

I found some headers that work. 我发现一些头文件有效。 I don't really know or care why it work, I am just happy it works... I tried a ton of different things, .htaccess files, php.ini / zlib settings. 我真的不知道或不在乎它为什么起作用,我很高兴它能起作用...我尝试了很多不同的东西,.htaccess文件,php.ini / zlib设置。

Here's the answer http://perishablepress.com/http-headers-file-downloads/ 答案是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);
}

Here is what works 这是有效的

$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);
}

Often the issue is caused by extra characters that have been printed or echo'd to the page before you read out the file. 通常,此问题是由在读取文件之前已打印或回显页面的多余字符引起的。 Even a space will cause the failure. 即使有空间也会导致故障。 To fix that issue, call ob_end_clean(); 要解决该问题,请调用ob_end_clean(); before you read the file which will clear the output buffer and turn off buffering. 在读取文件之前,这将清除输出缓冲区并关闭缓冲。

But keep in mind you can have nested output buffers, and this will corrupt your download as well (cheers to Vladamir for figuring this out). 但是请记住,您可以嵌套输出缓冲区,这也会破坏您的下载(请向Vladamir表示感谢)。 So to clear the output buffer completely run this before you read your file: 因此,要清除输出缓冲区,请在读取文件之前完全运行此命令:

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

This will clear out your entire buffer and you won't have any extra characters to mess up your download. 这将清除您的整个缓冲区,并且您不会有任何多余的字符来破坏您的下载。

For those interested i've pasted my download script below. 对于那些感兴趣的人,我在下面粘贴了我的下载脚本。 My zip files now download perfectly, and so far this works great. 我的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;
}

Well, I presume you know that your $fsize variable is not being written to that header because it's enclosed by quotes. 好吧,我想您知道您的$ fsize变量没有被写入该标头,因为它用引号引起来。 You could try something like this: 您可以尝试这样的事情:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM