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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3133209/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 08:48:07  来源:igfitidea点击:

How to flush output after each `echo` call?

phpapacheechoflush

提问by cusspvz

I have a php script that only produces logs to the client.
When I echo something, I want it to be transferred to client on-the-fly.
(Because while the script is processing, the page is blank)
I had already played around with ob_start()and ob_flush(), but they didn't work.

我有一个 php 脚本,它只向客户端生成日志。
当我回显某些内容时,我希望将其即时传输到客户端。
(因为在处理脚本时,页面是空白的)
我已经玩过ob_start()ob_flush(),但它们不起作用。

What's the best solution?

最好的解决办法是什么?

PS: it is a little dirty to put a flush at the end of the echocall...

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

EDIT: Neither the Answers worked, PHP or Apache Fault?

编辑:答案都不起作用,PHP 还是 Apache 故障?

采纳答案by amphetamachine

Edit:

编辑:

I was reading the comments on the manual page and came across a bugthat states that ob_implicit_flushdoes not workand the following is a workaround for it:

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

ob_end_flush();

# CODE THAT NEEDS IMMEDIATE FLUSHING

ob_start();

If this does not work then what may even be happening is that the client does not receive the packet from the server until the server has built up enough characters to send what it considers a packet worth sending.

如果这不起作用,那么甚至可能发生的情况是客户端不会从服务器接收数据包,直到服务器建立足够的字符来发送它认为值得发送的数据包。



Old Answer:

旧答案:

You could use ob_implicit_flushwhich will tell output buffering to turn off buffering for a while:

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

ob_implicit_flush(true);

# CODE THAT NEEDS IMMEDIATE FLUSHING

ob_implicit_flush(false);

回答by Teno

I've gotten the same issue and one of the posted example in the manual worked. A character set must be specified as one of the posters here already mentioned. http://www.php.net/manual/en/function.ob-flush.php#109314

我遇到了同样的问题,并且手册中发布的示例之一有效。必须将字符集指定为此处已经提到的海报之一。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 />';

回答by Roger

So here's what I found out.

所以这就是我发现的。

Flush would not work under Apache's mod_gzip or Nginx's gzip because, logically, it is gzipping the content, and to do that it must buffer content to gzip it. Any sort of web server gzipping would affect this. In short, at the server side we need to disable gzip and decrease the fastcgi buffer size. So:

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

  • In php.ini:

    output_buffering = Off
    
    zlib.output_compression = Off
    
  • In nginx.conf:

    gzip  off;
    
    proxy_buffering  off;
    
  • 在 php.ini 中:

    output_buffering = Off
    
    zlib.output_compression = Off
    
  • 在 nginx.conf 中:

    gzip  off;
    
    proxy_buffering  off;
    

Also have these lines at hand, especially if you don't have access to php.ini:

手头还有这些行,特别是如果您无权访问 php.ini:

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

@ini_set('implicit_flush',1);

@ob_end_clean();

set_time_limit(0);

Last, if you have it, comment the code bellow:

最后,如果你有的话,评论下面的代码:

ob_start('ob_gzhandler');

ob_flush();

PHP test code:

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

回答by nobody

Flushing seemingly failing to work is a side effect of automatic character set detection.

冲洗看似无法正常工作是自动字符集检测的副作用。

The browser will not display anything until it knows the character set to display it in, and if you don't specify the character set, it need tries to guess it. The problem being that it can't make a good guess without enough data, which is why browsers seem to have this 1024 byte (or similar) buffer they need filled before displaying anything.

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

The solution is therefore to make sure the browser doesn't have to guess the character set.

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

If you're sending text, add a '; charset=utf-8' to its content type, and if it's HTML, add the character set to the appropriate meta tag.

如果您要发送文本,请添加一个 '; charset=utf-8' 到其内容类型,如果是 HTML,则将字符集添加到适当的元标记。

回答by Ari Waisberg

For those coming in 2018:

对于 2018 年即将到来的人:

The ONLY Solution worked for me:

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

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

and its very important to keep de "4096" part because it seems that "fills" the buffer...

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

回答by GSto

what you want is the flushmethod. example:

你想要的是flush方法。例子:

echo "log to client";
 flush();

回答by cam8001

Why not make a function to echo, like this:

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

function fecho($string) {
 echo $string;
 ob_flush();
}

回答by freedayum

I had a similar thing to do. Using

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

// ini_set("output_buffering", 0);  // off 
ini_set("zlib.output_compression", 0);  // off
ini_set("implicit_flush", 1);  // on   

did make the output flushing frequent in my case.

在我的情况下确实使输出刷新频繁。

But I had to flush the output right at a particular point(in a loop that I run), so using both

但是我必须在特定点(在我运行的循环中)刷新输出,因此同时使用

ob_flush();
flush();

together worked for me.

一起为我工作。

I wasn't able to turn off "output_buffering"with ini_set(...), had to turn it directly in php.ini, phpinfo() shows its setting as "no value" when turned off, is that normal? .

我无法使用 ini_set(...)关闭“output_buffering”,必须直接在 php.ini 中打开它,关闭时 phpinfo() 将其设置显示为“无值”,这正常吗?.

回答by Dennis G

The correct function to use is flush().

要使用的正确函数是flush().

<html>
<body>
<p>
Hello! I am waiting for the next message...<br />
<?php flush(); sleep(5); ?>
I am the next message!<br />
<?php flush(); sleep(5); ?>
And I am the last message. Good bye.
</p>
</body>
</html>

Please note that there is a "problem" with IE, which only outputs the flushed content when it is at least 256 byte, so your first part of the page needs to be at least 256 byte.

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

回答by Radacina

This works fine for me (Apache 2.4/PHP 7.0):

这对我来说很好(Apache 2.4/PHP 7.0):

@ob_end_clean();
echo "lorem ipsum...";
flush();
sleep(5);
echo "<br>dolor...";
flush();
sleep(5);
echo "<br>sit amet";