【问题标题】:Creating and serving zipped files with php使用 php 创建和提供压缩文件
【发布时间】:2010-11-29 00:07:07
【问题描述】:

我正在尝试使用以下代码从目录创建一个 zip 文件并通过 http 下载将其提供给用户:

 // write the file
file_put_contents($path . "/index.html", $output);

// zip up the contents
chdir($path);
exec("zip -r {$course->name} ./");

$filename = "{$course->name}.zip";

header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename=' .urlencode($filename));
header('Content-Transfer-Encoding: binary');

readfile($filename);

我可以创建 zip 文件,但无法通过 http 下载。如果我下载使用 ftp 客户端创建的 zip 文件,那么 Mac 的 Stuffit Expander 会很好地解压缩文件,但如果我通过 http 下载它,mac 解压缩器会创建一个无限循环。我的意思是说我下载的文件名为 course.zip,然后解压缩该文件会得到 course.zip.cpgz,然后解压缩该文件会得到 course.zip 再次......等等。

有人有什么想法吗?

谢谢!

【问题讨论】:

  • 您的 application/octet-stream 的 mime 类型没有错误,但使用 application/zip 可能更友好。
  • @Tony Miller - 为什么不把它作为答案呢?很可能是这里的问题。
  • 如何从 php 进行“即时压缩和流式传输”:stackoverflow.com/a/4357904/416630

标签: php zip gzip unzip


【解决方案1】:

我遇到了这个问题,结果下载的 zip 文件在开头插入了一个新行。

使用 ob_clean 和 flush 函数解决

    header("Pragma: public");
    header("Expires: 0");
    header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
    header("Cache-Control: private",false);
    header("Content-Type: application/octet-stream");
    header("Content-Disposition: attachment; filename=".basename($archive_file_name));
    header("Content-Transfer-Encoding: binary");
    header("Content-Length: ".filesize($archive_file_name));
    ob_clean();
    flush();
    echo readfile("$archive_file_name");

【讨论】:

    【解决方案2】:
    1. 每次请求时都重新压缩它不是一个好主意。仅当 ZIP 文件不存在时才尝试这样做。

    2. 如果是易失文件或只是要传输压缩的单个小文件,请尝试使用ob_start('ob_gzhandler'),更简单、更小、更干净。该文件被压缩传输,但它被客户端保存为原始格式。

    3. 需要指定 Content-Length 标头以允许下载程序知道文件的结尾,从而允许进度控制、文件损坏检测并避免 HTTP 会话挂起(如果 Connection 处于 Keep -Alive 模式),也许缺少这个 header 才是问题的根源。

    【讨论】:

    • 我现在也指定了 Content-Length 标头,但它仍然不起作用。我基本上只是想一次向用户提供大约 15 个小文件,并且认为压缩是我唯一的选择。还有其他方法吗?
    【解决方案3】:

    正如karim79 所建议的那样,我将把我的评论作为答案:如果将 MIME 类型从 application/octet-stream 更改为 application/zip 会发生什么?

    另外,我看到您正在使用命令行 zip 程序,但您没有检查 zip 是否成功,也没有在尝试将文件发送到最终用户浏览器之前检查文件是否存在.尝试对文件名进行硬编码,手动使用 zip 以确保 zip 文件格式正确,然后查看您的代码是否会正确地将其发送到浏览器。

    【讨论】:

    • 好的,我尝试将 MIME 类型更改为 application/zip 以及在我知道格式正确的 zip 文件中进行硬编码(在我的计算机和服务器上都成功解压缩的文件上传后)并得到相同的结果。
    【解决方案4】:

    您看到的是存档实用程序没有将 zip 文件识别为 zip 文件,并试图压缩 zip 存档本身。第二个操作只是解压缩创建的第一个文件,因此根本不会真正打开文件。这是由于 zip 已损坏。

    在下载过程中,浏览器可能会以某种方式破坏 zip 文件(换行符转换?)。如前所述,检查 mime 类型并使用 php header() 设置正确的 MIME 类型(应用程序/zip)。

    【讨论】:

    • 好的,我尝试使用 application/zip,但没有成功。浏览器下载对话框向我表明我正在尝试下载“PC Zip 存档”,当它下载到我的机器时,OS X 显示“Kind:ZIP 存档”,但当我尝试解压缩它时它会做同样的事情。 (这也是一个硬编码的文件,我没有在上传之前在我的机器上运行压缩文件)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-10
    • 2015-05-04
    • 1970-01-01
    • 1970-01-01
    • 2014-08-26
    相关资源
    最近更新 更多