<?php
for($i=0;$i<20;$i++)
{
echo 'printing...<br />';
ob_flush();
flush();
usleep(300000);
}
?>
包含代码的网址:http://domainsoutlook.com/sandbox/delayed.php
我有一个专用服务器,所以我可以进行更改。我正在运行apache和nginx作为代理服务器。
答案 0 :(得分:37)
这就是我发现的:
Flush在Apache的mod_gzip或Nginx的gzip下不起作用,因为从逻辑上讲,它正在压缩内容,为此,它必须缓冲内容以对其进行gzip。任何类型的Web服务器gzipping都会影响这一点。简而言之,在服务器端,我们需要禁用gzip并减少fastcgi缓冲区大小。所以:
在php.ini中:
。 output_buffering =关
。 zlib.output_compression =关
在nginx.conf中:
。 gzip off;
。 proxy_buffering off;
还有这些线,特别是如果你没有访问php.ini:
@ini_set( '要用zlib.output_compression',0);
@ini_set( 'implicit_flush',1);
@ob_end_clean();
参数或者set_time_limit(0);
最后,如果你拥有它,请注意以下代码:
ob_start( 'ob_gzhandler');
使用ob_flush();
PHP测试代码:
ob_implicit_flush(1);
for($i=0; $i<10; $i++){
echo $i;
//this is for the buffer achieve the minimum size in order to flush data
echo str_repeat(' ',1024*64);
sleep(1);
}
答案 1 :(得分:11)
主要php文件;
<?php
header('Content-Type: text/HTML; charset=utf-8');
header( 'Content-Encoding: none; ' );//disable apache compressed
session_start();
ob_end_flush();
ob_start();
set_time_limit(0);
error_reporting(0);
..... bla bla
for(each)........
{
bla bla..
echo "<br>>>>".$i."<<<br>";
ob_flush();
flush(); //ie working must
}
?>
它正在运作..
答案 2 :(得分:9)
您使用的ob_flush
没有ob_start
,因此无需刷新。
它还取决于网络服务器和代理及其设置。
您应该为Nginx禁用缓冲(将“proxy_buffering off;”添加到配置文件并重新启动Nginx)
另外,检查你的php.ini是否包含“output_buffering = Off”和“zlib.output_compression = Off”。
答案 3 :(得分:1)
另一个可能的原因是mod_security。看起来它有自己的缓冲区。因此,如果您正在使用它,则必须设置:
SecResponseBodyAccess Off
一种肮脏的解决方法,但到目前为止,这是我让它工作的唯一方法。
答案 4 :(得分:1)
您必须填充缓冲区,以便可以将其刷新到浏览器。 在echo
之后使用它echo str_pad('',4096)."\n";
完整代码:
<?php
if (ob_get_level() == 0) ob_start();
for( $i=0 ; $i<20 ; $i++) {
echo 'printing...<br />';
echo str_pad('',4096)."\n";
ob_flush();
flush();
usleep(300000);
}
ob_end_flush();
?>
答案 5 :(得分:1)
只想补充Roger的答案。
如果您在 Apache2 中使用FastCGI php5-fpm 模块,您还必须确保添加
<强> -flush 强>
Apache2配置中的参数,即
<IfModule mod_fastcgi.c>
...
FastCgiExternalServer /usr/lib/cgi-bin/php5-fcgi -flush -socket /tmp/php5-fpm.sock -idle-timeout 480 -pass-header Authorization
</IfModule>
答案 6 :(得分:0)
正如我所读到的,它似乎是一个非常难以解决的问题,而我发现的唯一(脏)方法就是写一些无用的输出来填充≠缓冲区。 - 没有ssl - 没有output_buffering,需要刷新,可以降低nginx缓冲区,直到php头大小 - 使用output_buffering,需要添加ob_flush以具有与上面相同的行为 - 使用ssl,还有另一个缓冲区用于ssl和NGX_SSL_BUFSIZE在nginx编译中修复
这是我的test.php文件(用?size = ...调用它来改变循环中的空格写入)
<!DOCTYPE html>
<html>
<head></head>
<body>
<?php
$vars = array('output_buffering', 'zlib.output_compression');
print('<p>');
foreach ($vars as $var) {
print("$var : ");
var_dump(ini_get($var));
print('<br />');
}
print("ob_get_level() : " .ob_get_level());
print('</p>');
if (ob_get_level()) {
$bytes = ob_get_length();
ob_flush();
}
$nb_iterations = !empty($_GET['nb']) ? max(2, (int) $_GET['nb']) : 5;
$size = !empty($_GET['size']) ? $_GET['size'] : 0;
for ($i = 1; $i < $nb_iterations; $i++) {
sleep(1);
print(str_repeat(' ', 1024 * $size ));
print("<p>wait $i s</p>");
if (ob_get_level()) {
$bytes += ob_get_length();
print($bytes + strlen($bytes));
ob_flush(); // this is working, results aren't depending on output_buffering value
}
flush(); // this is needed
}
?>
</body>
</html>
我可以设置的下限是
location ~ ^/test.php$ {
gzip off;
fastcgi_pass unix:/var/run/php5-fpm/ssl.socket;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param SCRIPT_FILENAME $request_filename;
# if too low => upstream sent too big header while reading response header from upstream
fastcgi_buffer_size 128;
fastcgi_buffers 2 128;
fastcgi_busy_buffers_size 128;
}
答案 7 :(得分:0)
在php.ini中:
output_buffering =关闭 zlib.output_compression =关
在nginx.conf中:
fastcgi_keep_conn on; #&lt;溶液
proxy_buffering off; gzip off;
答案 8 :(得分:0)
我注意到浏览器的反应不同。例如,Chrome会永久保留输入,并且似乎并不关心如何更早地显示它。 不出所料,如果上面的提示(由其他stackoverflowers贡献),Firefox将更早地显示输入,所以尝试使用Firefox。
答案 9 :(得分:0)
我只能这样冲洗 - 添加session_write_close();
if (ob_get_level() == 0)
{
if(!ob_start("ob_gzhandler"))ob_start();
}
echo ('bla bla bla');
$ans=ob_get_contents();
ob_end_clean();
header('Connection: close');
header('Content-Length: '.strlen($ans));
header('Status: 200');
echo $ans;
session_write_close();
ob_flush();
flush();
答案 10 :(得分:0)
使用
检查服务器APIecho phpinfo();
如果找到了服务器api
Server API : CGI/FastCGI
在CentOS中然后在“/etc/httpd/conf.d/fcgid.conf”中添加这一行
OutputBufferSize 0
要测试,请重新启动Apache服务器并尝试下面的代码
ob_start();
for($i = 0; $i < 10; $i ++) {
echo $i;
echo '<br />';
flush();
ob_flush();
sleep(1);
}
答案 11 :(得分:0)
if(!ob_get_level()) ob_start();
echo json_encode(array('valid'=>true,'msg'=>'Flush occured.'));
$size = ob_get_length();
header("Content-Type: application/json");
// Set the content length of the response.
header("Content-Length: {$size}");
//Close the connection if you want to.
header("Connection: close");
// Flush all output.
ob_end_flush();
ob_flush();
flush();
// Close current session (if it exists).
if(session_id()) session_write_close();
答案 12 :(得分:0)
在ngnx上使用php-fpm时,我已经尝试了很多次。只是说明了许多答案:
在php.ini中:
output_buffering = Off
zlib.output_compression = Off
在nginx.conf中:
gzip off;
proxy_buffering off;
但是他们忘记了nginx.conf中非常重要的设置:
fastcgi_keep_conn on;