使用 php 创建和提供压缩文件

发布于 2024-08-04 21:52:14 字数 705 浏览 10 评论 0原文

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

有人有什么想法吗?

谢谢!

I'm trying to use the following code to create a zip file from a directory and serve it to the user via an http download:

 // 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);

I am able to create the zip file, but downloading it over http is not working. If I download the zip file that's created using an ftp client then Mac's Stuffit Expander unzips the files just fine, but if I download it over http, the mac unzipper creates an endless loop. What I mean by this is say the file I download is called course.zip, then unzipping the file gives course.zip.cpgz and unzipping that file gives course.zip again..and on and on.

Anyone have any ideas?

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

情泪▽动烟 2024-08-11 21:52:14

我遇到了这个问题,结果发现下载的 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");

I had this problem and it turned out the downloaded zip file had a new line inserted at the very beginning.

Solved by using ob_clean and flush functions

    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");
幻梦 2024-08-11 21:52:14
  1. 每次请求时都重新压缩它不是一个好主意。仅当 ZIP 文件尚不存在时才尝试执行此操作。

  2. 如果您想要传输压缩的易失性文件或只是一个小文件,请尝试使用 ob_start('ob_gzhandler') 代替,更简单、更小、更干净。文件以压缩方式传输,但客户端会以原始格式保存。

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

  1. Re-zipping it every time it is requested is not a good idea. Try doing that only if the ZIP file does not exist already.

  2. If is a volatile file or just a single small file you want to transfer compressed, try using ob_start('ob_gzhandler') instead, simplier, smaller, cleaner. The file is transfered compressed, but it is saved in its original format by the client-side.

  3. Specifying the Content-Length header is needed to allow the downloader to know the end of the file, allowing progress control, detection of corruption of the file and avoiding the hang of the HTTP session (if Connection is in Keep-Alive mode), maybe the lack of this header is the root of the problem.

椵侞 2024-08-11 21:52:14

正如 karim79 所建议的,我将把我的评论作为答案:如果您从 application/ 更改 MIME 类型,会发生什么八位字节流到应用程序/zip?

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

As suggested by karim79, I'll put my comment as an answer: what happens if you change the MIME type from application/octet-stream to application/zip?

Also, I see you're using a command line zip program, but you don't check for success of the zip, and also don't check if the file exists before attempting to send it out to the end users browser. Try hard coding a file name, manually using zip to guarantee a properly formed zip file, and then see if your code will spit it to your browser properly.

何以笙箫默 2024-08-11 21:52:14

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

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

What you're seeing is that the archive utility is not recognizing the zip file as a zip file, and tried to zip up the zip archive itself. The second operation simply unzips the first file created, so never actually opening the file at all. This is due to the zip being corrupted.

It is possible that the browser somehow mangled the zip file (newline conversions anyone?) during the download process. As mentioned, check the mime type and use the php header() to set the correct MIME type (application/zip).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文