web-dev-qa-db-ja.com

phpフラッシュが機能しない

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

    usleep(300000);
}

?>

コードを含むURL: http://domainsoutlook.com/sandbox/delayed.php

専用サーバーを持っているので、変更を加えることができます。プロキシサーバーとしてApacheとnginxを実行しています。

15
Speedy Wap

ob_flushなしでob_startを使用しているため、フラッシュするものはありません。

また、Webサーバーとプロキシおよびその設定にも依存します。

Nginxのバッファリングを無効にする必要があります(設定ファイルに「proxy_bufferingoff;」を追加してNginxを再起動します)

また、php.iniに「output_buffering = Off」と「zlib.output_compression = Off」が含まれているかどうかを確認してください。

9
schnaader

それが私が見つけたものです:

フラッシュは、論理的にはコンテンツをgzipで圧縮しているため、Apacheのmod_gzipまたはNginxのgzipでは機能しません。そのためにはコンテンツをバッファリングしてgzipで圧縮する必要があります。あらゆる種類のWebサーバーのgzipがこれに影響します。つまり、サーバー側では、gzipを無効にして、fastcgiバッファーサイズを減らす必要があります。そう:

  • Php.iniの場合:

    。 output_buffering =オフ

    。 zlib.output_compression =オフ

  • Nginx.conf内:

    。 gzipオフ;

    。 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);
}
38
Roger

メインの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

}
?>

それは働いています。

11
Emin Kadıoğlu

ブラウザにフラッシュできるように、バッファをいっぱいにする必要があります。エコー後にこれを使用します

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

もう1つの考えられる原因は、mod_securityです。独自のバッファがあるようです。したがって、それを使用している場合は、設定する必要があります:

SecResponseBodyAccess Off

一種の汚い回避策ですが、これまでのところ、それが私がそれを機能させる唯一の方法でした。

1
Chris Koston

ロジャーの答えに追加したかっただけです。

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>
1
Lukasz

私はこの方法でしかフラッシュできませんでした-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
It_Never_Works

php.ini

output_buffering = Off
zlib.output_compression = Off

nginx.conf

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

ブラウザの反応が異なることに気づきました。たとえば、Chromeは入力を永久に保持し、それ以前に表示することを気にしないようです。当然のことながら、上記のヒント(他のstackoverflowersによる貢献)が適用されている場合、Firefoxは入力を早く表示するので、Firefoxを試してみてください。

0
Rolf

私が読んでいるように、解決するのは本当に難しいpbのようです、そして私が見つけた唯一の(汚い)方法は≠バッファを満たすために出力するのに役に立たない何かを書くことです。 --sslなし-output_bufferingなし、flushが必要、phpヘッダーサイズまでnginxバッファーを下げることができます-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;
}
0
dcaillibaud

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;
0
Envy
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
RahulD

サーバー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
gsm