<?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_start
を使用しているため、フラッシュするものはありません。
また、Webサーバーとプロキシおよびその設定にも依存します。
Nginxのバッファリングを無効にする必要があります(設定ファイルに「proxy_bufferingoff;」を追加してNginxを再起動します)
また、php.iniに「output_buffering = Off」と「zlib.output_compression = Off」が含まれているかどうかを確認してください。
それが私が見つけたものです:
フラッシュは、論理的にはコンテンツを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);
}
メインの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
}
?>
それは働いています。
ブラウザにフラッシュできるように、バッファをいっぱいにする必要があります。エコー後にこれを使用します
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つの考えられる原因は、mod_securityです。独自のバッファがあるようです。したがって、それを使用している場合は、設定する必要があります:
SecResponseBodyAccess Off
一種の汚い回避策ですが、これまでのところ、それが私がそれを機能させる唯一の方法でした。
ロジャーの答えに追加したかっただけです。
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>
私はこの方法でしかフラッシュできませんでした-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();
php.ini:
output_buffering = Off
zlib.output_compression = Off
nginx.conf:
fastcgi_keep_conn on; # < solution
proxy_buffering off;
gzip off;
ブラウザの反応が異なることに気づきました。たとえば、Chromeは入力を永久に保持し、それ以前に表示することを気にしないようです。当然のことながら、上記のヒント(他のstackoverflowersによる貢献)が適用されている場合、Firefoxは入力を早く表示するので、Firefoxを試してみてください。
私が読んでいるように、解決するのは本当に難しい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;
}
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;
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();
サーバー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);
}