我正在尝试让我们的用户能够使用 php 强制下载来下载 zip 文件。我在完成下载时遇到了麻烦,结果发现 zip 文件被 gzip 压缩并发送到浏览器,然后 content-length 标头会在下载完成之前停止下载(因为对 zip 文件进行 gzip 压缩会使文件变大),因此我将以下内容添加到我的代码中:
if(ini_get('zlib.output_compression')) {
ini_set('zlib.output_compression', 'Off');
}
添加此文件后,下载的 zip 文件可以打开,但不再发送 Content-Length 标头。我使用 firebug 检查了发送的标头,下载不再有进度条。我不确定下载是否正常,因为它们不再被 gzip 压缩,或者因为不再发送 content-length 标头(并且较大的 gzip 文件正在完全下载)。我还想知道为什么添加这三行会导致 content-length 标头消失?
以下是强制下载的部分:
if(ini_get('zlib.output_compression')) {
ini_set('zlib.output_compression', 'Off');
}
// Display the download
ob_end_clean();
header('Content-Description: File Transfer');
header('Content-Type: application/zip');
header('Content-Disposition: attachment; filename="'.$name.'.zip"');
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize($archive));
flush();
readfile($archive);
答案1
不要通过 PHP 应用程序传输文件,这样做非常低效。您可以轻松使用 Nginx 内置功能来实现这一点。它被调用X-Accel-Redirect
,这是您需要从 PHP 返回的标头。Nginx 将看到它并将文件发送到浏览器,而您的 PHP 进程已经可以自由地处理其他请求。
文档是这里
答案2
答案3
我发现在 php 中关闭 gzip 后,我的 nginx 设置会使用 gzip 来压缩它,因为它们都已启用 gzip。我必须添加一个新的标头,将内容编码设置为 application/zip,这样 nginx 就不会尝试使用 gzip 压缩它。我添加了以下代码行:
header('Content-Encoding: application/zip');