【发布时间】:2010-08-13 09:51:10
【问题描述】:
我正在编写一个 PHP 脚本,该脚本会在不预先知道长度的情况下即时生成大型(多 MB)输出。我正在通过fwrite() 直接写信给php://output,并尝试了标准输出和使用Transfer-Encoding: chunked(根据需要对块进行编码),但无论我尝试什么,浏览器都会等到所有数据都写入后才会显示下载对话框.我也试过flush()ing 在标题之后和每个块之后,但这也没有区别。
我猜 Apache 正在缓存输出,因为浏览器在从服务器接收到几 kB 后通常会显示。
有没有人知道如何停止这种缓存并将数据在生成时刷新到浏览器?
谢谢, J
【问题讨论】:
-
我建议使用wireshark 或类似工具查看正在向浏览器发送哪些数据,而不是猜测apache 在生成整个内容之前不会刷新。如果您需要放慢速度,请插入一些
sleep(1)调用。 (我怀疑 Apache 在刷新其缓冲区之前会在单个套接字上维护几兆字节。) -
我的猜测是,您在 php.ini 和/或 apache 配置中启用了 GZIP 压缩。在这种情况下,apache 总是缓存。还没有找到避免这种情况的方法(除了禁用压缩),所以让我们看看其他人对此有何了解。可能是 serverfault.com 的问题,不过...
-
@sarnold - 当我说我猜这是一个有根据的猜测,因为我一直在通过 Fiddler 跟踪请求并且在下载对话框出现之前看不到任何响应,所以我很有信心它在服务器端缓存。 @BlaM-您说启用了GZIP是绝对正确的,我不认为这是可能的原因,因为它是流压缩算法,但这可能是问题所在。我会尝试禁用这个特定的脚本,看看会发生什么。谢谢。
-
@user290796,啊哈,那不是真的“猜测”! :) 如果@BlaM 是正确的,也许您可以编写自己的 Apache 输出过滤器来发送定期 FLUSH 存储桶,以保持 gzip 的好处。 (对于保存大文件似乎真的很有用。)
-
是的,虽然我不能 100% 确定 Fiddler 在显示之前没有等待完整的输出,所以它有点猜测;)。无论如何,要输出的文件实际上是一个 ZIP 文件,因此它已经被压缩,因此保留 GZIP 可能没有太大的好处,但输出过滤器可能是一个选项。我现在不在服务器附近尝试禁用 GZIP,但我会在今天晚些时候尝试一下。