PHP 内容长度标头未指定强制下载的大小

PHP 内容长度标头未指定强制下载的大小

我正在尝试让我们的用户能够使用 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

执行以下操作之一:

  • 修改 ob_end_clean 为 ob_clean
  • 彻底删除 ob_end_clean

我真的不知道为什么会这样。bugs.php.net可能会发现一些东西。

答案3

我发现在 php 中关闭 gzip 后,我的 nginx 设置会使用 gzip 来压缩它,因为它们都已启用 gzip。我必须添加一个新的标头,将内容编码设置为 application/zip,这样 nginx 就不会尝试使用 gzip 压缩它。我添加了以下代码行:

    header('Content-Encoding: application/zip');

相关内容