PHP下载脚本在Mac上创建不可读的ZIP文件

时间:2012-09-13 17:15:19

标签: php macos download zip

作为参考,我已经阅读并尝试了以下几个主题中的答案:

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代码将Zip文件下载到我的Mac时,使用Safari或Firefox,我收到一条错误,说“解压缩失败”或“存档的结构已损坏”或者我得到了。 cpgz文件 - 我相信这意味着计算机正在压缩文件,而不是解压缩它。

  4. 这是我用来传递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);
    }
    

3 个答案:

答案 0 :(得分: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);
}

答案 1 :(得分:5)

通常问题是由您在读出文件之前打印或回显到页面的额外字符引起的。即使是空间也会导致失败。要解决该问题,请在读取文件之前调用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;
}

答案 2 :(得分:0)

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

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