Php 如何在每次“echo”调用后刷新输出?

Php 如何在每次“echo”调用后刷新输出?,php,apache,echo,flush,Php,Apache,Echo,Flush,我有一个只向客户端生成日志的php脚本。 当我回显某个内容时,我希望它能够在运行中传输到客户端。 (因为在处理脚本时,页面是空白的) 我已经玩过ob\u start()和ob\u flush(),但它们都不起作用 最好的解决方案是什么 附言:在echo调用的末尾刷新有点脏 编辑:答案都不起作用,PHP或Apache错误 你想要的是方法。 例如: 正确使用的函数是flush() 你好我正在等待下一条消息… 我是下一条消息 我是最后一条信息。再见。 请注意,IE有一个“问题”,它只在刷新内容

我有一个只向客户端生成日志的php脚本。
当我回显某个内容时,我希望它能够在运行中传输到客户端。
(因为在处理脚本时,页面是空白的)
我已经玩过
ob\u start()
ob\u flush()
,但它们都不起作用

最好的解决方案是什么

附言:在
echo
调用的末尾刷新有点脏

编辑:答案都不起作用,PHP或Apache错误

你想要的是方法。 例如:


正确使用的函数是
flush()



你好我正在等待下一条消息…
我是下一条消息
我是最后一条信息。再见。


请注意,IE有一个“问题”,它只在刷新内容至少为256字节时才输出刷新内容,因此页面的第一部分需要至少为256字节。

为什么不创建一个echo函数,如下所示:

function fecho($string) {
 echo $string;
 ob_flush();
}
编辑:

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);
}
我在阅读手册页面上的评论时发现,
ob\u implicit\u flush
不起作用,以下是解决方法:

ob_end_flush();

# CODE THAT NEEDS IMMEDIATE FLUSHING

ob_start();
如果这不起作用,那么甚至可能发生的情况是,在服务器建立足够的字符以发送它认为值得发送的数据包之前,客户端不会从服务器接收数据包


旧答案:

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);
}
您可以使用以下命令来指示输出缓冲关闭缓冲一段时间:

ob_implicit_flush(true);

# CODE THAT NEEDS IMMEDIATE FLUSHING

ob_implicit_flush(false);

我也有类似的事情要做。使用

// ini_set("output_buffering", 0);  // off 
ini_set("zlib.output_compression", 0);  // off
ini_set("implicit_flush", 1);  // on   
在我的情况下,输出经常刷新

但我必须在某个特定点(在我运行的循环中)刷新输出,所以使用这两种方法

ob_flush();
flush();
一起为我工作

我没能做到 使用关闭“输出缓冲” ini_set(…),必须直接将其旋转 在php.ini中,phpinfo()显示其设置 关闭时为“无值”,是吗 正常吗


这就是我发现的

Flush在Apache的mod_gzip或Nginx的gzip下不起作用,因为从逻辑上讲,它是gzip内容,要做到这一点,它必须将内容缓冲到gzip中。任何类型的web服务器gzip都会影响这一点。简而言之,在服务器端,我们需要禁用gzip并减小fastcgi缓冲区大小。因此:

  • 在php.ini中:

    output_buffering = Off
    
    zlib.output_compression = Off
    
  • 在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 to make the buffer achieve the minimum size in order to flush data
    echo str_repeat(' ',1024*64);

    sleep(1);
}
ob\u隐式\u刷新(1);

对于($i=0;$i),刷新失败是自动字符集检测的副作用

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

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


如果您发送文本,请在其内容类型中添加“;charset=utf-8”,如果是HTML,请将字符集添加到相应的元标记中。

我收到了相同的问题,并且手册中发布的一个示例已生效。必须将字符集指定为此处已提到的海报之一

标题('Content-type:text/html;charset=utf-8');
回显“开始…
”; 对于($i=0;$i<10;$i++) { 回显$i。“
”; 冲洗(); ob_flush(); 睡眠(1); } 回显“结束…
”;
有时,问题来自Apache设置。可以将Apache设置为gzip输出。 在.htaccess文件中,您可以添加以下内容,例如:

SetEnv no-gzip 1
试试这个:

while (@ob_end_flush());      
ob_implicit_flush(true);

echo "first line visible to the browser";
echo "<br />";

sleep(5);

echo "second line visible to the browser after 5 secs";

反病毒软件也可能会干扰输出刷新。在我的情况下,卡巴斯基反病毒2013在将数据块发送到浏览器之前保存了数据块,即使我使用的是公认的解决方案。

注意,如果您在某些共享托管网站(如Dreamhost)上,如果不通过不同路线:

如果您使用的是PHP FastCGI,则更改输出缓冲区缓存 函数flush()、ob_flush()和ob_implicit_flush()将不会 按预期运行。默认情况下,输出缓冲在更高级别 而不是PHP(具体地说,是通过Apache模块mod_deflate 在形式/功能上类似于mod_gzip)

如果需要无缓冲输出,则必须使用CGI(而不是 FastCGI)或联系支持部门请求禁用mod_deflate 为您的网站


我的讨论迟到了,但我读到很多人说在每个代码的末尾添加flush();看起来很脏,他们是对的

最佳解决方案是禁用来自Apache、中间处理程序和PHP的deflate、gzip和所有缓冲。然后在PHP.ini中您应该有:

            output_buffering = Off
            zlib.output_compression = Off
            implicit_flush = Off
临时解决方案是在php.ini中包含这个如果你可以用flush()解决你的问题;但是你认为把它放在任何地方都是肮脏和丑陋的

implicit_flush = On
如果只将其放在php.ini中,则不需要再将flush()放在代码中。

这是我的代码:(为PHP7工作)


对于2018年即将到来的人:

唯一对我有效的解决方案是:

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

保留de“4096”部分非常重要,因为它似乎“填充”了缓冲区…

这对我来说很好(Apache 2.4/PHP7.0):

@ob_end_clean();
回声“同侧眼底……”;
冲洗();
睡眠(5);
回声“
多洛……”; 冲洗(); 睡眠(5); 回声“
坐在阿梅特”;
一件不常提及的事情是gzip压缩,由于各种托管环境中的细节,它一直处于打开状态

这是一个
implicit_flush = On
private function closeConnection()
{
    @apache_setenv('no-gzip', 1);
    @ini_set('zlib.output_compression', 0);
    @ini_set('implicit_flush', 1);

    ignore_user_abort(true);
    set_time_limit(0);

    ob_start();
    // do initial processing here
    echo json_encode(['ans' => true]);

    header('Connection: close');
    header('Content-Length: ' . ob_get_length());
    ob_end_flush();
    ob_flush();
    flush();
}
<?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();
?>
@ob_end_clean();
echo "lorem ipsum...";
flush();
sleep(5);
echo "<br>dolor...";
flush();
sleep(5);
echo "<br>sit amet";
output_buffering = 0
zlib.output_compression = 0
implicit_flush = true
output_handler = 
header('Content-Encoding: none'); // Disable gzip compression
ob_end_flush(); // Stop buffer
ob_implicit_flush(1); // Implicit flush at each output command