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

PHP下载脚本在Mac上创建不可读的ZIP文件,php,macos,download,zip,Php,Macos,Download,Zip,作为参考,我已经阅读并尝试了这些和其他几个线程中的答案: 我的服务器上有一个zip文件 当我使用Filezilla将Zip文件从服务器移动到Mac时,我可以正常打开它 当我使用这个PHP代码将Zip文件下载到我的Linux机器上时,它会正常打开 当我使用这个PHP代码使用Safari或Firefox将Zip文件下载到Mac电脑时,我会收到一个错误,说“解压缩失败”或“存档结构损坏”,或者我收到一个.cpgz文件,我相信这意味着计算机正在压缩文件,而不是解压缩文件 下面是我用来传递zip文件的

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

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

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

  • 当我使用这个PHP代码将Zip文件下载到我的Linux机器上时,它会正常打开

  • 当我使用这个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设置

    答案是这样的


    好吧,我假设您知道$fsize变量没有被写入到该头中,因为它是用引号括起来的。 您可以尝试以下方法:

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

    好吧,我假设您知道$fsize变量没有被写入到该头中,因为它是用引号括起来的。 您可以尝试以下方法:

    header('Cache-Control: public');
    header('Content-Description: File Transfer');
    header('Content-Disposition: attachment; filename=\"".$zipname."\"');
    header('Content-Type: application/zip');
    
    这就是有效的方法

    $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()读取文件之前,该文件将清除输出缓冲区并关闭缓冲

    但请记住,您可以使用嵌套的输出缓冲区,这也会损坏您的下载(为解决此问题而干杯)。因此,要完全清除输出缓冲区,请在读取文件之前运行以下命令:

    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_end_clean()读取文件之前,该文件将清除输出缓冲区并关闭缓冲

    但请记住,您可以使用嵌套的输出缓冲区,这也会损坏您的下载(为解决此问题而干杯)。因此,要完全清除输出缓冲区,请在读取文件之前运行以下命令:

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


    替换
    echo fpassthru($downloadzip)时会发生什么情况
    by
    readfile($zippath)?您是否尝试过删除:
    header('Content-Transfer-Encoding:binary')?当我使用
    readfile()
    时,它的大小是0.2MB,这是非常小的。我删除了
    标题('Content-Transfer-Encoding:binary')但这没有什么区别。当您替换
    echo fpassthru($downloadzip)时会发生什么
    by
    readfile($zippath)?您是否尝试过删除:
    header('Content-Transfer-Encoding:binary')?当我使用
    readfile()
    时,它的大小是0.2MB,这是非常小的。我删除了
    标题('Content-Transfer-Encoding:binary')但没有区别。$fsize应该可以工作,它被双引号包围,而不是单引号。我确实认为$fsize可以工作,当我注释掉标题行时,下载不知道文件有多大。当标题行被使用时,下载的人确实知道文件有多大。@Chris我的错误。尝试将大小添加到我提供的上述标题中,看看是否有效。@chriscct7您的标题给了我相同的最终结果$fsize应该可以工作,它被双引号包围,而不是单引号。我确实认为$fsize可以工作,当我注释掉标题行时,下载不知道文件有多大。当标题行被使用时,下载的人确实知道文件有多大。@Chris我的错误。尝试将大小添加到我提供的上述标题中,看看是否有效。@chriscct7您的标题给了我相同的最终结果数小时后,您的周期解决了我的问题。清洗每个缓冲区就是解决办法。很高兴我能帮上忙。在我在另一个网站上找到这个解决方案之前,它也让我陷入了一个循环。快乐的编码…我已经努力了好几个小时了。万分感谢马克西姆斯!我从来没有想过ob_get_level循环会完成这项工作!谢谢几个小时后,你的自行车解决了我的问题。清洗每个缓冲区就是解决办法。很高兴我能帮上忙。在我在另一个网站上找到这个解决方案之前,它也让我陷入了一个循环。快乐的编码…我已经努力了好几个小时了。万分感谢马克西姆斯!我从来没有想过ob_get_level循环会完成这项工作!谢谢美好的我的问题在safari中通过添加
    ob_end_flush()在读取文件之前结束。要强调的是,我在Safarinice中下载zip文件和.html扩展名时遇到了问题。。我的问题在safari中通过添加
    ob_end_flush()在读取文件之前结束。要强调的是,我在Safari中下载zip文件和.html扩展名时遇到了一个问题