php 刷新不起作用

问题描述 投票:0回答:14
<?php
for($i=0;$i<20;$i++)
{
    echo 'printing...<br />';
    ob_flush();
    flush();

    usleep(300000);
}

?>

包含代码的网址:http://domainsoutlook.com/sandbox/delayed.php

我有一个专用服务器,因此我可以进行更改。我正在运行 apache 和 nginx 作为代理服务器。

php flush
14个回答
48
投票

这就是我发现的:

Flush 在 Apache 的 mod_gzip 或 Nginx 的 gzip 下无法工作,因为从逻辑上讲,它正在对内容进行 gzip 压缩,并且要做到这一点,它必须缓冲内容以对其进行 gzip。任何类型的 Web 服务器 gzip 压缩都会影响这一点。简而言之,在服务器端,我们需要禁用 gzip 并减小 fastcgi 缓冲区大小。所以:

  • 在 php.ini 中:

    。输出缓冲=关闭

    。 zlib.output_compression = 关闭

  • 在 nginx.conf 中:

    。 gzip 关闭;

    。 proxy_buffering 关闭;

手边还有这行代码,特别是如果您无法访问 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);
}

13
投票

您使用的是

ob_flush
而没有
ob_start
,所以没有什么可以冲洗的。

这还取决于网络服务器和代理及其设置。

您应该禁用 Nginx 的缓冲(将

proxy_buffering off;
添加到配置文件并重新启动 Nginx)

另外,检查您的 php.ini 是否包含

output_buffering = Off
zlib.output_compression = Off


12
投票

主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

}
?>

它正在工作..


5
投票

您必须填充缓冲区,以便将其刷新到浏览器。 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();
?>

4
投票

php.ini:

output_buffering = Off
zlib.output_compression = Off

nginx.conf:

fastcgi_keep_conn on; # < solution
proxy_buffering off;
gzip off;

3
投票

正如我所读,这似乎是一个很难解决的问题,我发现的唯一(脏)方法是编写一些无用的输出来填充 ≠ 缓冲区。

  • 没有 SSL
    • 没有output_buffering,需要
      flush

      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;
}

1
投票

另一个可能的原因是 mod_security。看起来它有自己的缓冲区。因此,如果您正在使用它,则必须进行设置:

SecResponseBodyAccess Off

这是一种肮脏的解决方法,但到目前为止,这是我让它工作的唯一方法。


1
投票

只是想补充一下罗杰的答案。

如果您在 Apache2 中使用 FastCGI php5-fpm 模块,您还必须确保添加

-齐平

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>

1
投票

检查您的服务器 API

echo 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);
}

0
投票

我注意到浏览器的反应有所不同。例如,Chrome 会永远保留输入,并且似乎并不关心是否提前显示它。 不出所料,如果应用了上述提示(由其他 stackoverflower 提供),Firefox 会更早地显示输入,所以请尝试使用 Firefox。


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();

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();

0
投票

我在使用 php-fpm 和 nginx 时尝试了很多次。许多答案只是指示:

在 php.ini 中:

output_buffering = Off

zlib.output_compression = Off

在 nginx.conf 中:

gzip off;

proxy_buffering off;

但是他们忘记了 nginx.conf 中非常重要的设置:

fastcgi_keep_conn on;

0
投票

这是唯一对我有用且无需填充的解决方案。

<?php
set_time_limit(0); # remove the time limit for running the script
ob_end_clean();

#header('Cache-Control: no-cache'); # activate if chaching is an issue
#header('Pragma: no-cache'); # activate if chaching is an issue
header('Connection: close');
header('Transfer-Encoding: identity');

ob_implicit_flush(1);

for($i=0;$i<5;$i++){
    echo json_encode(array(
        'timestamp'=>time(),
    ));
    usleep(500000);
}
?>

它给出了以下输出:

HTTP/1.1 200 OK
Date: Sat, 25 Nov 2023 11:54:24 GMT
Server: Apache/2.4.57 (Unix) PHP/7.4.33
X-Powered-By: PHP/7.4.33
Connection: close
Transfer-Encoding: identity, chunked
Content-Type: text/html; charset=UTF-8
 
18
{"timestamp":1700913264}
18
{"timestamp":1700913265}
18
{"timestamp":1700913265}
18
{"timestamp":1700913266}
18
{"timestamp":1700913266}
0
© www.soinside.com 2019 - 2024. All rights reserved.