2012-01-23 19 views
6

PHPスクリプトの出力ストリームを閉じることはできますか?後処理を行う必要があるスクリプトがありますが、後処理中と後でクライアントにデータを送信することはありませんので、後処理の前に接続を終了したいと考えています。PHP:閉じる出力ストリーム

編集:私のアプリケーションでは、私はいつでも再構築する必要があるキャッシュを持っています。しかし、私はユーザーを減速させたくありません。私が望むのは、キャッシュを再構築する必要があるかどうかをスクリプトの最後で判断することです。だから私は出力ストリームを最初に閉じて、ユーザーがデータを取得してからキャッシュを再構築したいと思っています。これを行うことは本当に重要なことではありませんが、最初に接続を閉じるほうがよいと思います。そのため、ユーザーは長い時間がかかるとキャッシュが再構築されていることに気付かないでしょう。

+0

なぜあなたはこれを実行する必要がありますか?もう少し理解を深めるためのコードを少し投稿できますか? –

+0

+1にジョナサンが言った。なぜあなたがこれをやりたいのか、もう少し私たちに教えてください。 –

答えて

4

UPDATEは

このケースを処理するための方法は、出力バッファと適切なHTTPヘッダーの組み合わせです。

HTTP/1.1 Specification Section 14.10より:

HTTP/1.1は、接続が 反応の完了後にクローズされること 信号を送信者の「クローズ」接続オプションを定義します。

我々は接続に加えて、HTTP のContent-Lengthヘッダに沿って渡すのであれば、:近い、ブラウザは、指定された応答長が受信された後、接続を閉じることを知っている:

  1. 完全な出力データを取得したら、適切なヘッダーをクライアントに送信してください。
  2. rの処理...しかし、出力を送信しようとしないか、ヘッダーが送信されているため、エラーが発生します。

また、あまりにも多くの処理を行うと、WebサーバーSAPIでスクリプトの実行時間制限を超えて実行できないように注意してください。最後に、ignore_user_abort()を使用してこの特定のスクリプトの「ユーザ打ち切り」を無視するようにPHPに指示する必要があります。これは、実行中の結果としてブラウザが接続を終了し、PHPが処理を続行するようにするためです。

<?php 
ignore_user_abort(); 
ob_start(); 

// do stuff, generate output 

// get size of the content 
$length = ob_get_length(); 

// tell client to close the connection after $length bytes received 
header('Connection: close'); 
header("Content-Length: $length"); 

// flush all output 
ob_end_flush(); 
ob_flush(); 
flush(); 

// close session if you have one ... 
// continue your processing tasks ... 
?> 

あなたはConnection handlingdocs上のPHPマニュアルのセクションを検討することがあります。

また、出力バッファリングを開始しないでください。その後、送信されるすべての出力をキャプチャし、実際に何かをしたい場合は後で決定することができます。

<?php 

echo 'before output buffering'; 
ob_start(); 
echo 'after output buffering'; 
$output = ob_get_contents(); 

// script's only output to this point will be 'before output buffering' 

// I changed my mind, send the output ... 
ob_end_flush(); 
?> 
+0

出力バッファリングは、ブラウザへの出力ストリームを開いたままにします。だから私は数秒かかるいくつかの後処理を行う必要があると仮定し、ブラウザはその後処理が完了するまで待つでしょう。特にAJAXを使用すると、Webアプリケーションが大幅に遅くなります。だから私はブラウザへの接続を閉じることができるようにしたいので、ブラウザは出力を処理して、後処理を続けることができます。 – Tiddo

+0

@Tiddo私は(私が信じている)正しい答えで私の答えを更新しました。 – rdlowrey

+0

それはかなり良い解決策です!私はそれを数分で試してみるつもりです。編集:それは素晴らしい作品!どうもありがとう! – Tiddo

0

私がコメントするのに十分な評判を持っていないが、私は@rdlowreyの答えにgzipのが問題になる可能性があることを共有したいと思います。

あなたは転送エンコーディングヘッダーは常にに設定されているのgzipを有効にしている場合は、それゆえ、それはのContent-Lengthヘッダを送信しませんheader("Transfer-encoding: none");でそれを変更しようとした場合でも、チャンク。私はこの問題を解決することができ

の方法は、使用していた次の前に:その後、

<? 
@ini_set('zlib.output_compression', 'Off'); 
@ini_set('output_buffering', 'Off'); 
@ini_set('output_handler', ''); 
@apache_setenv('no-gzip', 1); 
?> 

そしてソリューション:

<? 
ignore_user_abort(); 
ob_start(); 

// do stuff, generate output 

// get size of the content 
$length = ob_get_length(); 

// tell client to close the connection after $length bytes received 
header('Connection: close'); 
header("Content-Length: $length"); 

// flush all output 
ob_end_flush(); 
flush(); 

// close session if you have one ... 
// continue your processing tasks ... 
?> 
関連する問題