php flush не работает - PullRequest
       33

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

12 голосов
/ 16 января 2011
<?php
for($i=0;$i<20;$i++)
{
    echo 'printing...<br />';
    ob_flush();
    flush();

    usleep(300000);
}

?>

URL-адрес, содержащий код: http://domainsoutlook.com/sandbox/delayed.php

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

Ответы [ 12 ]

38 голосов
/ 12 февраля 2011

Так вот что я узнал:

Flush не будет работать под mod_gzip Apache или gzip Nginx, потому что, по логике, он распаковывает содержимое, и для этого он должен буферизовать содержимое, чтобы сжать его. Любой вид взлома веб-сервера повлияет на это. Короче говоря, на стороне сервера нам нужно отключить 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');

Тестовый код 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);
}
11 голосов
/ 09 января 2013

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

}
?>

это работает ..

9 голосов
/ 16 января 2011

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

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

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

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

2 голосов
/ 09 апреля 2014

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

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();
?>
1 голос
/ 07 мая 2014

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

Если вы используете 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>
1 голос
/ 12 июня 2013

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

SecResponseBodyAccess Off

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

0 голосов
/ 18 июля 2017
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();
0 голосов
/ 07 декабря 2016

Проверьте ваш сервер 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);
}
0 голосов
/ 10 октября 2016

Мне удалось сбросить только таким способом - добавив 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();
0 голосов
/ 07 мая 2014

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

...