PHP Flush that works… even in Nginx

前端 未结 8 828
既然无缘
既然无缘 2020-11-30 22:29

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

相关标签:
8条回答
  • 2020-11-30 23:04

    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:

    • In php.ini:

      . output_buffering = Off

      . zlib.output_compression = Off

    • In nginx.conf:

      . gzip off;

      . proxy_buffering off;

    Also have this lines at hand, specially if you don't have acces to 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, coment the code bellow:

    • ob_start('ob_gzhandler');

    • ob_flush();

    PHP test code:

    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:

    • php flush not working

    • How to flush output after each `echo` call?

    • PHP flushing output as soon as you call echo

    0 讨论(0)
  • 2020-11-30 23:04

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

    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 :

    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";
    }
    
    0 讨论(0)
  • 2020-11-30 23:08

    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

    0 讨论(0)
  • 2020-11-30 23:12

    Easy solution on nginx server:

    fastcgi_keep_conn on; # < solution
    
    proxy_buffering off;
    gzip off;
    
    0 讨论(0)
  • 2020-11-30 23:13

    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.

    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.

    0 讨论(0)
  • 2020-11-30 23:14

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

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

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

    0 讨论(0)
提交回复
热议问题