我正在尝试使用以下代码从目录创建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 unzipper会创建一个无限循环。我的意思是说我下载的文件名为course.zip,然后解压缩文件给出course.zip.cpgz并解压缩该文件再次给出course.zip ..然后再打开。

有人有什么想法吗?

谢谢!

有帮助吗?

解决方案

  1. 每次请求时重新压缩它都不是一个好主意。只有当ZIP文件不存在时才尝试这样做。

  2. 如果是易失性文件或只想传输压缩文件的小文件,请尝试使用 ob_start('ob_gzhandler'),更简单,更小,更清晰。该文件已传输压缩,但由客户端以原始格式保存。

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

其他提示

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

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

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

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

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top