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

<?php for($i=0;$i<20;$i++) { echo 'printing...<br />'; ob_flush(); flush(); usleep(300000); } ?> 

Url, который содержит код: http://domainsoutlook.com/sandbox/delayed.php

У меня есть выделенный сервер, поэтому я могу внести изменения. Я использую apache и nginx в качестве прокси-сервера.

Вы используете ob_flush без ob_flush , поэтому для него нечего ob_flush .

Это также зависит от веб-сервера и прокси-сервера и его настроек.

Вы должны отключить буферизацию для Nginx (добавьте «proxy_buffering off» в конфигурационный файл и перезапустите Nginx)

Кроме того, проверьте, содержит ли ваш php.ini «output_buffering = Off» и «zlib.output_compression = Off».

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

Флеш не работал бы с помощью 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;

 <?php header('Content-Type: text/HTML; charset=utf-8'); header( 'Content-Encoding: none; ' );//disable apache compressed session_start(); ob_end_flush(); ob_start(); set_time_limit(0); error_reporting(0); ..... bla bla for(each)........ { bla bla.. echo "<br>>>>".$i."<<<br>"; ob_flush(); flush(); //ie working must } ?> 

работает..

Другой возможной причиной является mod_security. Похоже, что у него есть собственные буферы. Поэтому, если вы используете его, вам придется установить:

 SecResponseBodyAccess Off 

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

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

 echo str_pad('',4096)."\n"; 

Полный код:

 <?php if (ob_get_level() == 0) ob_start(); for( $i=0 ; $i<20 ; $i++) { echo 'printing...<br />'; echo str_pad('',4096)."\n"; ob_flush(); flush(); usleep(300000); } ob_end_flush(); ?> 

Просто хотел добавить к ответу Роджера.

Если вы используете модуль FastCGI php5- fpm в Apache2, вы также должны убедиться, что добавляете

-промывать

аргумент в вашей конфигурации Apache2, т.е.

 <IfModule mod_fastcgi.c> ... FastCgiExternalServer /usr/lib/cgi-bin/php5-fcgi -flush -socket /tmp/php5-fpm.sock -idle-timeout 480 -pass-header Authorization </IfModule> 

Как я читал, это кажется очень трудным pb для решения, и единственный (грязный) способ, который я нашел, пишет что-то бесполезное для вывода, чтобы заполнить буферы. – без ssl – без output_buffering, необходим сброс, буферы nginx могут быть опущены до тех пор, пока размер заголовка php – с output_buffering, ob_flush необходимо добавить, чтобы иметь такое же поведение, как и выше – с ssl, есть еще один буфер для ssl и NGX_SSL_BUFSIZE исправлено в компиляции nginx

Вот мой файл test.php (назовите его с? Size = … для изменения записи пространства в цикле)

 <!DOCTYPE html> <html> <head></head> <body> <?php $vars = array('output_buffering', 'zlib.output_compression'); print('<p>'); foreach ($vars as $var) { print("$var : "); var_dump(ini_get($var)); print('<br />'); } print("ob_get_level() : " .ob_get_level()); print('</p>'); if (ob_get_level()) { $bytes = ob_get_length(); ob_flush(); } $nb_iterations = !empty($_GET['nb']) ? max(2, (int) $_GET['nb']) : 5; $size = !empty($_GET['size']) ? $_GET['size'] : 0; for ($i = 1; $i < $nb_iterations; $i++) { sleep(1); print(str_repeat(' ', 1024 * $size )); print("<p>wait $i s</p>"); if (ob_get_level()) { $bytes += ob_get_length(); print($bytes + strlen($bytes)); ob_flush(); // this is working, results aren't depending on output_buffering value } flush(); // this is needed } ?> </body> </html> 

И нижний conf, который я могу установить, – это

 location ~ ^/test.php$ { gzip off; fastcgi_pass unix:/var/run/php5-fpm/ssl.socket; fastcgi_param QUERY_STRING $query_string; fastcgi_param REQUEST_METHOD $request_method; fastcgi_param SCRIPT_FILENAME $request_filename; # if too low => upstream sent too big header while reading response header from upstream fastcgi_buffer_size 128; fastcgi_buffers 2 128; fastcgi_busy_buffers_size 128; } 

В php.ini:

output_buffering = Выкл. zlib.output_compression = Выкл.

В nginx.conf:

fastcgi_keep_conn on; # <решение

proxy_buffering off; gzip off;

Я заметил, что браузеры реагируют по-разному. Например, Chrome хранится на входе навсегда и, похоже, не заботится о его отображении ранее. Неудивительно, что Firefox будет отображать ввод раньше, если применяются приведенные выше советы (внесенные другими stackoverflowers), поэтому попробуйте Firefox.

Я смог выполнить только этот способ: добавление session_write_close ();

 if (ob_get_level() == 0) { if(!ob_start("ob_gzhandler"))ob_start(); } echo ('bla bla bla'); $ans=ob_get_contents(); ob_end_clean(); header('Connection: close'); header('Content-Length: '.strlen($ans)); header('Status: 200'); echo $ans; session_write_close(); ob_flush(); flush(); 

Проверьте свой сервер api с помощью

 echo phpinfo(); 

Если вы нашли свой сервер api

 Server API : CGI/FastCGI 

в CentOS добавьте эту строку в "/etc/httpd/conf.d/fcgid.conf"

 OutputBufferSize 0 

Чтобы проверить, перезапустите сервер Apache и попробуйте выполнить код ниже

 ob_start(); for($i = 0; $i < 10; $i ++) { echo $i; echo '<br />'; flush(); ob_flush(); sleep(1); } 
 if(!ob_get_level()) ob_start(); echo json_encode(array('valid'=>true,'msg'=>'Flush occured.')); $size = ob_get_length(); header("Content-Type: application/json"); // Set the content length of the response. header("Content-Length: {$size}"); //Close the connection if you want to. header("Connection: close"); // Flush all output. ob_end_flush(); ob_flush(); flush(); // Close current session (if it exists). if(session_id()) session_write_close();