web-dev-qa-db-ja.com

各「echo」コールの後に出力をフラッシュする方法は?

クライアントにのみログを生成するphpスクリプトがあります。
何かをエコーするとき、オンザフライでクライアントに転送したいです。
(スクリプトの処理中はページが空白になるため)
ob_start()ob_flush()で遊んでいましたが、うまくいきませんでした。

最適なソリューションは何ですか?

PS:echo呼び出しの最後にフラッシュを置くのは少し汚いです...

編集:回答が機能しませんでしたPHPまたはApache Fault?

54
cusspvz

編集:

私はマニュアルページの称賛を読んでいたときに遭遇しました バグ それはob_implicit_flushは機能しません。以下はその回避策です。

ob_end_flush();

# CODE THAT NEEDS IMMEDIATE FLUSHING

ob_start();

何が起こっているのかもしれませんが、サーバーは、送信する価値のあるパケットと見なされるものを送信するのに十分な文字をサーバーが構築するまで、サーバーからパケットを受信しません。


古い回答:

ob_implicit_flush これは、出力バッファリングにしばらくバッファリングをオフにするよう指示します。

ob_implicit_flush(true);

# CODE THAT NEEDS IMMEDIATE FLUSHING

ob_implicit_flush(false);
36
amphetamachine

同じ問題が発生し、マニュアルに掲載されている例の1つが機能しました。ここですでに述べたポスターの1つとして文字セットを指定する必要があります。 http://www.php.net/manual/en/function.ob-flush.php#109314

header( 'Content-type: text/html; charset=utf-8' );
echo 'Begin ...<br />';
for( $i = 0 ; $i < 10 ; $i++ )
{
    echo $i . '<br />';
    flush();
    ob_flush();
    sleep(1);
}
echo 'End ...<br />';
57
Teno

だからここに私が見つけたものがあります。

フラッシュは、Apacheのmod_gzipまたはNginxのgzipでは機能しません。これは、論理的にコンテンツをgzipしているため、gzipするためにコンテンツをバッファリングする必要があるためです。あらゆる種類のWebサーバーのgzip圧縮がこれに影響します。つまり、サーバー側で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 to make the buffer achieve the minimum size in order to flush data
    echo str_repeat(' ',1024*64);

    sleep(1);
}
34
Roger

動作しないように見えるフラッシュは、文字セットの自動検出の副作用です。

ブラウザは、表示する文字セットを認識するまで何も表示しません。文字セットを指定しない場合、推測を試行する必要があります。問題は、十分なデータがないとうまく推測できないことです。そのため、ブラウザは、表示する前にこの1024バイト(または同様の)バッファを埋める必要があるようです。

したがって、解決策は、ブラウザが文字セットを推測する必要がないようにすることです。

テキストを送信する場合は、「; charset = utf-8 'をコンテンツタイプに追加し、HTMLの場合は、適切なメタタグに文字セットを追加します。

11
nobody

2018年に来る人のために:

唯一のソリューションは私のために働いた:

<?php

    if (ob_get_level() == 0) ob_start();
    for ($i = 0; $i<10; $i++){

        echo "<br> Line to show.";
        echo str_pad('',4096)."\n";    

        ob_flush();
        flush();
        sleep(2);
    }

    echo "Done.";

    ob_end_flush();
?>

バッファを「埋める」ように見えるので、「4096」の部分を維持することが非常に重要です...

10
Ari Waisberg

欲しいのは flush メソッドです。例:

echo "log to client";
 flush();
7
GSto

次のように、エコーする関数を作成してください:

function fecho($string) {
 echo $string;
 ob_flush();
}
5
cam8001

使用する正しい関数はflush()です。

<html>
<body>
<p>
Hello! I am waiting for the next message...<br />
<?php flush(); sleep(5); ?>
I am the next message!<br />
<?php flush(); sleep(5); ?>
And I am the last message. Good bye.
</p>
</body>
</html>

IEには、フラッシュされたコンテンツが少なくとも256バイトの場合にのみ出力する「問題」があるため、ページの最初の部分は少なくとも256バイトである必要があることに注意してください。

3
Dennis G

似たようなことがありました。を使用して

// ini_set("output_buffering", 0);  // off 
ini_set("zlib.output_compression", 0);  // off
ini_set("implicit_flush", 1);  // on   

私の場合、出力のフラッシュが頻繁に行われました。

しかし、特定のポイント(実行中のループ内)で出力をフラッシュする必要があったため、両方を使用して

ob_flush();
flush();

一緒に働いてくれました。

"output_buffering" ini_set(...)でオフにできませんでした。php.iniで直接オンにする必要があり、phpinfo()はオフにすると「値なし」として設定を表示します、それは正常ですか? 。

3
freedayum

これは私にとってはうまくいきます(Apache 2.4/PHP 7.0):

@ob_end_clean();
echo "lorem ipsum...";
flush();
sleep(5);
echo "<br>dolor...";
flush();
sleep(5);
echo "<br>sit amet";
1
Radacina

ウイルス対策ソフトウェアが出力フラッシュを妨害している可能性もあります。私の場合、Kaspersky Anti-Virus 2013は、承認済みのソリューションを使用していても、ブラウザーに送信する前にデータチャンクを保持していました。

1
marcovtwout

頻繁に言及されていないことの1つは、さまざまなホスティング環境の詳細のためにオンに維持されるgzip圧縮です。

これは、PHP-FPMをFast CGIとして使用する最新のアプローチで、.htaccess書き換えルールや環境変数を必要としません。

Php.iniまたは.user.iniで:

output_buffering = 0
zlib.output_compression = 0
implicit_flush = true
output_handler = 

In PHP script:

header('Content-Encoding: none'); // Disable gzip compression
ob_end_flush(); // Stop buffer
ob_implicit_flush(1); // Implicit flush at each output command

this comment on official PHP ob_end_flush()の必要性に関するドキュメント)を参照してください。

1
ZalemCitizen

これは私のコードです:(PHP7で動作します)

private function closeConnection()
{
    @Apache_setenv('no-gzip', 1);
    @ini_set('zlib.output_compression', 0);
    @ini_set('implicit_flush', 1);

    ignore_user_abort(true);
    set_time_limit(0);

    ob_start();
    // do initial processing here
    echo json_encode(['ans' => true]);

    header('Connection: close');
    header('Content-Length: ' . ob_get_length());
    ob_end_flush();
    ob_flush();
    flush();
}
0
Dmitry Matrosov

私は議論に遅れていますが、多くの人がflush()を追加すると言っていることを読みました。各コードの終わりに汚れているように見え、それらは正しいです。

最良の解決策は、deflate、gzip、およびApache、中間ハンドラー、PHPからのすべてのバッファリングを無効にすることです。次に、php.iniに以下が必要です。

            output_buffering = Off
            zlib.output_compression = Off
            implicit_flush = Off

一時的な解決策これをphp.iniに含める[〜#〜] if [〜#〜] flush()で問題を解決できます。しかし、あなたはそれをどこにでも置くのは汚くていと思う。

implicit_flush = On

Php.iniに上記のみを配置する場合、flush()を配置する必要はありません。あなたのコードでもう。

0
Tarik

これを試して:

_while (@ob_end_flush());      
ob_implicit_flush(true);

echo "first line visible to the browser";
echo "<br />";

sleep(5);

echo "second line visible to the browser after 5 secs";
_

この方法で、現在のスクリプトの出力バッファを実際に無効にしていることに注意してください。 ob_start()で再度有効にできると思います(わかりません)。

重要なことは、上記のように出力バッファを無効にすると、header()関数を使用してphpスクリプトをリダイレクトできなくなることです。phpはスクリプト実行ごとに1回だけHTTPヘッダーを送信できるからです。ただし、javascriptを使用してリダイレクトできます。それに関しては、phpスクリプトに次の行をエコーさせるだけです。

_        echo '<script type="text/javascript">';
        echo 'window.location.href="'.$url.'";';
        echo '</script>';
        echo '<noscript>';
        echo '<meta http-equiv="refresh" content="0;url='.$url.'" />';
        echo '</noscript>'; 
        exit;
_
0
Grigoreas P.

Dreamhostのような特定の共有ホスティングサイトを使用している場合、別のルートを経由せずにPHP出力バッファリングを無効にすることはできません。

出力バッファキャッシュの変更PHP FastCGIを使用している場合、PHP関数flush()、ob_flush()、およびob_implicit_flush()は期待どおりに機能しません。デフォルトでは、出力はPHP(具体的にはApacheモジュールmod_deflateよりも高いレベルでバッファリングされますmod_gzipとフォーム/機能が似ています)。

バッファーなしの出力が必要な場合は、CGIを使用する(FastCGIの代わりに)か、サポートに連絡してmod_deflateを要求する必要がありますあなたのサイトでは無効です

https://help.dreamhost.com/hc/en-us/articles/214202188-PHP-overview

0
Matthew Lock