每次`echo`调用后如何刷新输出?

cus*_*pvz 54 php apache flush echo

我有一个PHP脚本,只生成日志到客户端.
当我回应某些内容时,我希望它能够即时转移到客户端.
(因为在脚本处理过程中,页面是空白的)
,我已经打得四处ob_start()ob_flush(),但他们没有工作.

什么是最好的解决方案?

PS:在echo通话结束时放一个同花牌有点脏......

编辑:Answers既不工作,PHP或Apache错误?

Ten*_*eno 58

我遇到了同样的问题,手册中的一个已发布的示例也奏效了.必须将字符集指定为此处提到的海报之一.http://www.php.net/manual/en/function.ob-flush.php#109314

header( 'Content-type: text/html; charset=utf-8' );
echo 'Begin ...<br />';
for( $i = 0 ; $i < 10 ; $i++ )
{
    echo $i . '<br />';
    flush();
    ob_flush();
    sleep(1);
}
echo 'End ...<br />';
Run Code Online (Sandbox Code Playgroud)

  • 我尝试了一切以使输出正常工作.让它最终起作用的是你的例子中的"Content-type"标题.谢谢你先生!!! (4认同)
  • 这里的例子和其他页面都不适合我。Linux with Apache and php 7 (2认同)
  • **代码不起作用。** 在wardspace 免费托管默认设置、firefox 上进行了测试。 (2认同)

amp*_*ine 36

编辑:

我正在阅读手册页上的评论,并发现了一个错误,指出它ob_implicit_flush 不起作用,以下是一个解决方法:

ob_end_flush();

# CODE THAT NEEDS IMMEDIATE FLUSHING

ob_start();
Run Code Online (Sandbox Code Playgroud)

甚至可能发生的是客户端在服务器已经构建足够的字符以发送它认为值得发送的数据包之前不会从服务器接收数据包.


旧答案:

您可以使用ob_implicit_flush哪个将告诉输出缓冲关闭缓冲一段时间:

ob_implicit_flush(true);

# CODE THAT NEEDS IMMEDIATE FLUSHING

ob_implicit_flush(false);
Run Code Online (Sandbox Code Playgroud)


Rog*_*ger 34

所以这就是我发现的.

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

也有这些行,特别是如果你没有访问php.ini:

@ini_set('zlib.output_compression',0);

@ini_set('implicit_flush',1);

@ob_end_clean();

set_time_limit(0);
Run Code Online (Sandbox Code Playgroud)

最后,如果你有,请注释下面的代码:

ob_start('ob_gzhandler');

ob_flush();
Run Code Online (Sandbox Code Playgroud)

PHP测试代码:

ob_implicit_flush(1);

for ($i=0; $i<10; $i++) {
    echo $i;

    // this is to make the buffer achieve the minimum size in order to flush data
    echo str_repeat(' ',1024*64);

    sleep(1);
}
Run Code Online (Sandbox Code Playgroud)

  • 对我来说答案的关键是`//这是为了缓冲区达到最小尺寸以便刷新数据echo str_repeat('',1024*64);` (3认同)
  • `echo str_repeat('',1024*64);`使`flush`工作.但是为什么我在其他地方找不到呢?文档没有提到它.... (2认同)

小智 12

看似无法工作的刷新是自动字符集检测的副作用.

浏览器在知道要显示的字符集之前不会显示任何内容,如果您没有指定字符集,则需要尝试猜测它.问题是如果没有足够的数据就无法做出好的猜测,这就是为什么浏览器在显示任何内容之前似乎需要填充这个1024字节(或类似)缓冲区的原因.

因此,解决方案是确保浏览器不必猜测字符集.

如果您要发送文字,请添加'; charset = utf-8'到其内容类型,如果是HTML,则将字符集添加到相应的元标记中.


Ari*_*erg 10

对于那些即将到来的人:

唯一的解决方案对我有用:

<?php

    if (ob_get_level() == 0) ob_start();
    for ($i = 0; $i<10; $i++){

        echo "<br> Line to show.";
        echo str_pad('',4096)."\n";    

        ob_flush();
        flush();
        sleep(2);
    }

    echo "Done.";

    ob_end_flush();
?>
Run Code Online (Sandbox Code Playgroud)

保持de"4096"部分非常重要,因为它似乎"填满"了缓冲区...

  • 但如果我增加 str_pad 值,效果会更好!4096000 其显示效果相当好。它绝对是浏览器处理的内容值。 (2认同)
  • 每一步发送4MB的文本数据是不是有点大材小用了? (2认同)
  • 经过一百万次尝试,这是唯一适合我使用 FastCGI 的代码。但是用4096不行。我必须使用 `str_pad('',1024*64);` (2认同)

GSt*_*Sto 7

你想要的是flush方法.例:

echo "log to client";
 flush();
Run Code Online (Sandbox Code Playgroud)

  • `ini_set('implicit_flush',true)`在输出块之后基本上会模拟一个flush(),它可以在任何地方设置(php.ini,.htaccess,per-script等...) (7认同)

cam*_*001 5

为什么不做一个回声函数,像这样:

function fecho($string) {
 echo $string;
 ob_flush();
}
Run Code Online (Sandbox Code Playgroud)


Zal*_*zen 5

不经常提及的一件事是 gzip 压缩,由于各种托管环境中的详细信息而保持打开状态。

这是一种现代方法,使用 PHP-FPM 作为 Fast CGI,不需要 .htaccess 重写规则或环境变量:

在 php.ini 或 .user.ini 中:

output_buffering = 0
zlib.output_compression = 0
implicit_flush = true
output_handler = 
Run Code Online (Sandbox Code Playgroud)

在 PHP 脚本中:

header('Content-Encoding: none'); // Disable gzip compression
ob_end_flush(); // Stop buffer
ob_implicit_flush(1); // Implicit flush at each output command
Run Code Online (Sandbox Code Playgroud)

有关 ob_end_flush() 的需要,请参阅官方 PHP 文档上的评论。


小智 5

header( 'X-Accel-Buffering: no' );
header( 'Content-Type: text/html; charset=utf-8' );

echo 'text to display';
echo '<span style="display: none;">' . str_repeat ( ' ', 4096 ) . '</span>';
flush();
usleep( 10 );
Run Code Online (Sandbox Code Playgroud)