繁体   English   中英

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

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

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

使用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);
}

这是有效的

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

通常,此问题是由在读取文件之前已打印或回显页面的多余字符引起的。 即使有空间也会导致故障。 要解决该问题,请调用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;
}

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

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