4

我正在尝试使用以下代码从目录创建一个 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 ......等等。

有人有想法么?

谢谢!

4

4 回答 4

8

我遇到了这个问题,结果下载的 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");
于 2009-11-23T16:06:07.007 回答
1

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

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

于 2009-09-17T01:20:07.883 回答
1
  1. 每次请求时都重新压缩它不是一个好主意。仅当 ZIP 文件不存在时才尝试这样做。

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

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

于 2009-09-17T01:23:03.537 回答
0

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

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

于 2009-09-17T01:22:19.393 回答