使用PHP和Apache防止输出缓冲

x8goxv8g  于 2023-08-07  发布在  Apache
关注(0)|答案(3)|浏览(176)

我有一个PHP脚本,它发送了大量的记录,我想尽快刷新每个记录:客户端能够在每个记录到达时对其进行处理,而不需要等待整个响应。我意识到整个传输需要稍长的时间,因为它需要在多个数据包中发送,但它仍然允许客户端更快地开始工作。
我已经尝试了所有不同的flush()ob_flush()函数,但似乎没有什么能帮助在页面完成之前实际发送数据。我已经确认它不是Web浏览器,因为我已经使用telnet测试过了。

92dk7w1h

92dk7w1h1#

对我来说唯一有效的解决方案是将php.ini中的output_buffering指令设置为“Off”。我不想对整个服务器这样做,只想对这一个特定的资源这样做。通常你可以在PHP脚本中使用ini_set,但是不管出于什么原因,php不允许以这种方式设置output_buffering(参见the php manual)。
事实证明,如果你使用Apache,你可以从你的服务器配置中设置一些php ini指令(包括output_buffering),包括一个.htaccess文件。所以我在一个.htaccess文件中使用了下面的代码来禁用这个文件的output_buffering:

<Files "q.php">
    php_value output_buffering Off
</Files>

字符串
然后在我的静态服务器配置中,我只需要AllowOverride Options=php_value(或更大的锤子,如AllowOverride All),以便在.htaccess文件中允许它。

hs1ihplo

hs1ihplo2#

你没有提到你使用的是什么Web服务器,但我在这里要冒险猜测Apache 2。我撞到了和你描述的几乎一样的东西。我试图让我的cgi脚本在它准备好的时候传递回信息,而不是缓冲整个事情。在curl等中可以工作,但在浏览器(几乎任何浏览器)中都可以缓冲,这至少让人抓狂。我完全按照你描述的步骤做了。在我的案例中,解决方案是修改Apache 2中的sites-enabled/terrifico.com配置文件(有问题的行以
设置环境IfNoCase
(You我可以忽略那条线上面和下面的东西,我只是为了参考我放置它的位置而显示它。

<VirtualHost *:80>
ServerAdmin webmaster@localhost
ServerName test.terrifico.com
ServerAlias test.terrifico.com

SetEnvIfNoCase Request_URI \.cgi$ no-gzip dont-vary

DocumentRoot /var/www/test.terrifico.com

字符串
从盯着来回的网络流量,我终于明白了,浏览器是广告,它接受任何通缩(这是文本)。例如,这就是浏览器和curl之间的区别。重点是
Accept-Encoding:gzip,deflate,sdch
有一点关于chunking,但这并没有影响这个特定的问题。所以,浏览器请求mod_deflate启动,这打败了我在cgi脚本中小心地吐出的字节。您可以在浏览器中更改它,但在服务器上更改一次似乎更明智。
也许这能帮上忙

ybzsozfc

ybzsozfc3#

要在PHP运行时关闭输出缓冲而不更改php.ini或拥有.htaccess文件,只需在脚本的开头使用ob_end_flush()ob_end_clean()。举例来说:
这应该不带缓冲输出:

<?php
@ob_end_clean();

for ($i = 0; $i < 5; $i++)
{
    echo "$i\n";
    flush();
    usleep(0.5e6);
}

字符串
如果output_buffering打开,则输出缓冲(一次全部),而不管flush()调用:

<?php

for ($i = 0; $i < 5; $i++)
{
    echo "$i\n";
    flush();
    usleep(0.5e6);
}


ob_implicit_flush在每次输出后都会隐式调用flush(),而不是ob_flush()。在这个示例中,在开始时关闭输出缓冲区后,这可能很方便:

<?php
@ob_end_clean(); // disable output buffer
ob_implicit_flush(); // call flush() automatically after every output

for ($i = 0; $i < 5; $i++)
{
    echo "$i\n";
    usleep(0.5e6);
}


这修复了PHP端。mod_deflate或类似的东西可能还有其他原因(请参阅Ted柯林斯的答案),我观察到Firefox在开始输出任何东西之前至少需要1024字节。

相关问题