Solaris 上有一个 Apache 服务器,它发送“Transfer-Encoding: chunked”,而不发送我 PHP 中的“Content-Length”标头(用于下载文件)。您知道如何防止这种情况发生吗?
谢谢
看:https://stackoverflow.com/questions/1334471/content-length-header-always-zero
我已经尝试过指令
SetEnvIfNoCase Request_URI get_file\.php$ no-gzip dont-vary
现在我得到了一个与原始文件大小相同的文件,但文件已损坏。以下是从服务器收到的标头:
http://example.com/output_file_download.php?fileID=130
GET /output_file_download.php?fileID=130 HTTP/1.1
Host: example.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.9.1.2) Gecko/20090729 Firefox/3.5.2 (.NET CLR 3.5.30729)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-gb,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Cookie: user_id=7C%25R; intrauser=kE06Ub%238+2dHT%29U0t%28B%2A; intrakey=rtacconi; PHPSESSID=5a3f8edff822474f3b95b6a6e5c87ad2
HTTP/1.x 200 OK
Date: Thu, 03 Sep 2009 10:02:05 GMT
Server: Apache
Expires: 0
Cache-Control: private
Pragma: public
Content-Description: File Transfer
Content-Disposition: attachment; filename=alfresco-logo.gif
Content-Transfer-Encoding: binary
Content-Length: 2401
Keep-Alive: timeout=15, max=500
Connection: Keep-Alive
Content-Type: application/octet-stream
答案1
分块输出发生在 Apache 在发送之前不知道总输出大小的情况下,就像压缩传输的情况一样(当数据达到一定大小时,Apache 会将数据压缩成块,然后在脚本仍在执行时将它们发送给浏览器/请求者)。您之所以看到这种情况,可能是因为您有mod_deflate
或mod_gzip
处于活动状态。您可以验证这是否是您的问题这里。
您可以mod_deflate
像这样禁用每个文件(更多内容)
SetEnvIfNoCase Request_URI get_file\.php$ no-gzip dont-vary
最好保持开启状态,因为它可以大大提高数据传输速度。
答案2
如果 Apache 2 输出过滤器看到流结束标记 (EOS) 并且尚未发送任何内容,它将自动添加内容长度标头。源代码:
if (ctx->data_sent == 0 && eos) {
ap_set_content_length(r, r->bytes_sent);
}
如果 PHP 在发送 EOS 之前将任何数据传递给 Apache,则会发生分块。默认情况下,PHP 使用 4096 字节的输出缓冲区。任何小于该大小的页面都不会被分块。
还要检查内容是否通过 gzip(mod_gzip)提供,并且压缩后 apache 将转为分块编码。