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 в качестве прокси-сервера.

Ответ 1

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

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

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

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

Ответ 2

Итак, что я узнал:

Флеш не будет работать под Apache mod_gzip или Nginx gzip, потому что он логически является 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);
}

Ответ 3

Основной файл 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

}
?>

он работает.

Ответ 4

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

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

Ответ 5

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

SecResponseBodyAccess Off

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

Ответ 6

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

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

-flush

в вашей конфигурации 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>

Ответ 7

Как я читал, кажется, что очень трудный 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;
}

Ответ 8

В php.ini:

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

В nginx.conf:

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

proxy_buffering off; gzip off;

Ответ 9

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

Ответ 10

Мне удалось выполнить только этот способ: добавление 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();

Ответ 11

Проверьте свой сервер 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);
}

Ответ 12

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

Ответ 13

Я пытался много раз при использовании php-fpm с nginx. Многие ответы просто наставляют:

В php.ini:

output_buffering = Off

zlib.output_compression = Off

В nginx.conf:

gzip off;

proxy_buffering off;

НО они забыли очень важный параметр в nginx.conf:

fastcgi_keep_conn on;