在PHP中禁用输出缓冲

5
我有一个任务对象,当执行__deconstruct()时,它会在页面的其余部分加载完毕后运行一些较长的清理任务。不幸的是,它缓冲了输出并且在任务完成之前不会发送任何内容(任务中没有打印)。我已经阅读了http://www.php.net/flush并尝试了其中的所有建议。显然,我已经尝试在php.ini中禁用output_buffering。我已经禁用了deflate_module,关闭了zlib压缩,没有mod_gzip。调用flush()或ob_flush()没有效果,启用implicit_flush也没有效果。我只是在Windows Server 2008 R2下运行XAMPP(当前apache 2.2.17,php 5.3.4)。PHP作为模块运行。是的,我可以设置一些小的AJAX hack来运行任务管理器,甚至设置一个计划任务来运行这个特定的任务,但输出缓冲在其他地方也是一个问题。有时候只想让它消失。从类似的线程中,有人建议看看以下内容会发生什么:
<?php
while (TRUE)
{
    echo 'x';
    flush();
    sleep(1);
}
?>

正如预期的那样,页面在达到最大执行时间之前不显示任何内容,此时它会刷新缓冲区。

这变得非常令人沮丧。有人有任何想法,还可能导致缓冲吗?


你能确认输出是否仍在缓冲,而不是浏览器没有显示任何内容(例如,IE在接收一定数量的字节之前不会显示任何内容)吗? - user212218
这个函数http://php.net/manual/en/function.ob-get-level.php返回0吗? - dqhendricks
你可以试试这个,看看它是否有帮助:http://in3.php.net/manual/zh/function.ob-end-flush.php - Saket Patel
我尝试了多个浏览器,所以我认为那不是问题。当我实际测试时,结果证明它确实是问题所在。而且,ob_get_level()返回0,因为那不是问题。 - Apropos
2个回答

4

嗯,很有趣。我在其他地方使用过一段代码片段,它的表现符合预期...

https://dev59.com/kGHVa4cB1Zd3GeqPoJfw#9728519

<?php
echo str_repeat('fillerbytes',20*1024/strlen('fillerbytes'));
echo '<body style="font-size:6px;font-family:arial;">';
echo str_repeat('<br>',2);
    for($i=1; $i<=5000; $i++){
        echo $i . ' ';
        ob_flush();
        flush();
        usleep(2000); // 2 ms each = 10s total
    }
?>

观察我的服务器数量增加到5000 http://atwebresults.com/texttest/new.php

(某些免费主机如freehostingeu.com无法使用。)


是的,这个可以工作。不幸的是,这只是因为它发送了比我想要发送的更多的数据。将迭代之间的时间从0.001秒改为1秒会导致不需要的行为再次出现。 - Apropos
这让我很开心。我认为它之所以有效是因为使用了 ob_flush(); 而不是 flush();。 - Alrik
这是由于发送的数据量而不是ob_flush()。即使添加了ob_flush(),原始示例仍会失败,或者当将迭代之间的时间更改为1秒而不是像当前一样的千分之一秒时,此示例也会失败。 - Apropos
@TimWick,注意只有在没有中间代理缓冲响应的情况下,向最终用户进行流式传输才有效。另请参见https://archive.is/e1jB#selection-1725.262-1725.307。 - Pacerier
@TimWickstrom,您使用哪家托管公司? - Pacerier

4
你只发送了少量数据。浏览器有自己的缓冲区,可以基于接收到的元素数量、字节数或其他方式进行设置。
简而言之,你无法对此进行任何操作。缓冲是在客户端而不是服务器端发生的。你可以尝试在发送 x 之前发送更多数据。
你可以使用 Wireshark 或类似工具来嗅探服务器和浏览器之间的连接以证明这一点。

好的,我本来想说我之前发送了相当多的数据,但是在将它更改为for($i=0;$i<10000;$i++){echo 'x<br />';sleep(1)}后,输出就正常了。我猜唯一的解决方法就是发送更多的数据来强制浏览器显示它。虽然可能不是理想的解决方案,但还是谢谢你。我一直在检查我的脚本和配置文件,这让我感到非常疯狂。 - Apropos
IE因此而出名。我通过在刷新之前发送大约1000个空格来欺骗IE。由于HTML混淆了空格,所以这并不重要。 - nalply

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接