PHP Flush 有效......即使在 Nginx 中

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4870697/
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 16:08:48  来源:igfitidea点击:

PHP Flush that works... even in Nginx

phpnginxflush

提问by Roger

Is it possible to echo each time the loop is executed? For example:

每次执行循环时都可以回显吗?例如:

foreach(range(1,9) as $n){
    echo $n."\n";
    sleep(1);
}

Instead of printing everything when the loop is finished, I'd like to see it printing each result per time.

我希望看到它每次打印每个结果,而不是在循环完成时打印所有内容。

回答by Andy Fowler

The easiest way to eliminate nginx's buffering is by emitting a header:

消除 nginx 缓冲的最简单方法是发出一个标头:

header('X-Accel-Buffering: no');

This eliminates both proxy_bufferingand (if you have nginx >= 1.5.6), fastcgi_buffering. The fastcgi bit is crucial if you're using php-fpm. The header is also far more convenient to do on an as-needed basis.

这消除了双方proxy_buffering和(如果你有nginx的> = 1.5.6) fastcgi_buffering。如果您使用 php-fpm,fastcgi 位是至关重要的。根据需要,标题也更方便。

Docs on X-Accel-BufferingDocs on fastcgi_buffering

X-Accel-Buffering文档 fastcgi_buffering 文档

回答by Roger

FINAL SOLUTION

最终解决方案

So that'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 中:

    . 输出缓冲 = 关

    . zlib.output_compression = 关

  • 在 nginx.conf 中:

    . gzip关闭;

    . 代理缓冲关闭;

Also have this lines at hand, specially if you don't have acces to php.ini:

手头也有这些行,特别是如果您没有访问 php.ini 的权限:

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

  • @ini_set('implicit_flush',1);

  • @ob_end_clean();

  • set_time_limit(0);

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

  • @ini_set('implicit_flush',1);

  • @ob_end_clean();

  • 设置时间限制(0);

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

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

  • ob_start('ob_gzhandler');

  • ob_flush();

  • ob_start('ob_gzhandler');

  • ob_flush();

PHP test code:

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

Related:

有关的:

回答by Ondrej Prochazka

Easy solution on nginx server:

nginx 服务器上的简单解决方案:

fastcgi_keep_conn on; # < solution

proxy_buffering off;
gzip off;

回答by Redzarf

I didn't want to have to turn off gzip for the whole server or a whole directory, just for a few scripts, in a few specific cases.

我不想为整个服务器或整个目录关闭 gzip,只为几个脚本,在一些特定情况下。

All you need is this before anything is echo'ed:

在回显任何内容之前,您只需要这个:

header('Content-Encoding: none;');

Then do the flush as normal:

然后照常进行冲洗:

ob_end_flush();
flush();

Nginx seems to pick up on the encoding having been turned off and doesn't gzip.

Nginx 似乎接受了已关闭的编码并且不进行 gzip。

回答by Petah

You need to flush the php's buffer to the browser

您需要将 php 的缓冲区刷新到浏览器

foreach(range(1,9) as $n){
    echo $n."\n";
    flush();
    sleep(1);
}

See: http://php.net/manual/en/function.flush.php

见:http: //php.net/manual/en/function.flush.php

回答by ttk

I found that you can set:

我发现你可以设置:

header("Content-Encoding:identity");

in your php script to disable nginx gzipping without having to modify the nginx.conf

在您的 php 脚本中禁用 nginx gzipping,而无需修改 nginx.conf

回答by Andy Baird

You can accomplish this by flushing the output buffer in the middle of the loop.

您可以通过在循环中间刷新输出缓冲区来完成此操作。

Example:

例子:

ob_start();
foreach(range(1,9) as $n){
    echo $n."\n";
    ob_flush();
    flush();
    sleep(1);
}

Note that your php.ini settings can affect whether this will work or not if you have zlib compression turned on

请注意,如果您打开了 zlib 压缩,您的 php.ini 设置会影响这是否有效

回答by Nicolas Thery

I had a gzip problem comming from my php-fpm engine. this code is the only one working for me :

我的 php-fpm 引擎出现了 gzip 问题。这段代码是唯一对我有用的代码:

function myEchoFlush_init() {
    ini_set('zlib.output_compression', 0);
    ini_set('output_buffering', 'Off');
    ini_set('output_handler', '');
    ini_set('implicit_flush', 1);
    ob_implicit_flush(1);
    ob_end_clean();
    header('Content-Encoding: none;');

}

function myEchoFlush($str) {
    echo $str . str_repeat(' ', ini_get('output_buffering') * 4) . "<br>\n";
}

This is my test function : it checks max_execution_time :

这是我的测试函数:它检查 max_execution_time :

public function timeOut($time = 1, $max = 0) {
    myEchoFlush_init();
    if ($max) ini_set('max_execution_time', $max);
    myEchoFlush("Starting infinite loop for $time seconds. It shouldn't exceed : " . (ini_get('max_execution_time')));
    $start = microtime(true);
    $lastTick = 1;
    while (true) {
        $tick = ceil(microtime(true) - $start);
        if ($tick > $lastTick) {
            myEchoFlush(microtime(true) - $start);
            $lastTick = $tick;
        }
        if ($tick > $time) break;
    }
    echo "OK";
}