PHP-флеш, который работает … даже в Nginx

Можно ли эхо каждый раз, когда цикл выполняется? Например:

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

Вместо того, чтобы печатать все, когда цикл закончен, я бы хотел, чтобы он печатал каждый результат за раз.

Solutions Collecting From Web of "PHP-флеш, который работает … даже в Nginx"

ОКОНЧАТЕЛЬНОЕ РЕШЕНИЕ

Вот что я узнал:

Флеш не работал бы с помощью apache mod_gzip или gzip от Nginx, потому что, по логике, это gzipping содержимое, и для этого он должен буферизовать контент, чтобы его gzip. Любой вид gzipping веб-сервера повлияет на это. Короче говоря, на стороне сервера нам нужно отключить 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 for the buffer achieve the minimum size in order to flush data echo str_repeat(' ',1024*64); sleep(1); } 

Связанный:

  • php flush не работает

  • Как очистить выходные данные после каждого вызова echo?

  • Вывод промывки PHP, как только вы вызываете эхо

Простое решение на сервере nginx:

 fastcgi_keep_conn on; # < solution proxy_buffering off; gzip off; 

Самый простой способ устранить буферизацию nginx – это исправить заголовок:

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

Это устраняет как proxy_buffering и (если у вас nginx> = 1.5.6), fastcgi_buffering . Бит fastcgi имеет решающее значение, если вы используете php-fpm. Заголовок также гораздо удобнее делать по мере необходимости.

Документы по документам X-Accel-Buffering на fastcgi_buffering

Я не хотел отключать gzip для всего сервера или целого каталога, всего лишь для нескольких скриптов, в нескольких конкретных случаях.

Все, что вам нужно, это прежде чем что-либо повторится:

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

Затем выполните флеш как обычно:

 ob_end_flush(); flush(); 

Кажется, что Nginx забирает кодировку, отключенную и не gzip.

Вам нужно сбросить буфер php в браузер

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

См .: http://php.net/manual/en/function.flush.php

Вы можете выполнить это, сбросив выходной буфер в середине цикла.

Пример:

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

Обратите внимание, что ваши настройки php.ini могут повлиять на то, будет ли это работать или нет, если вы включили сжатие zlib

Я обнаружил, что вы можете установить:

 header("Content-Encoding:identity"); 

в вашем скрипте php отключить nginx gzipping без необходимости изменения nginx.conf

У меня была проблема с gzip, исходящая от моего php-fpm engine. этот код работает только для меня:

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

Это моя тестовая функция: она проверяет 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"; }