2013-02-22 115 views
6

我有一個PHP腳本,它發送大量記錄,並且我希望在每個記錄可用時儘快刷新它:客戶端能夠處理每個記錄到達時,它不需要等待整個響應。我意識到整個傳輸需要稍長的時間,因爲它需要以多個數據包發送,但它仍然允許客戶端儘早開始工作。防止用PHP和Apache輸出緩衝

我已經嘗試了所有不同的flush()ob_flush()函數,但是在頁面結束之前似乎沒有任何東西可以幫助獲取通過行實際發送的數據。我已經確認它不是網絡瀏覽器,因爲我已經使用telnet對它進行了測試。

回答

4

唯一能解決問題的方案是將php.ini中的output_buffering指令設置爲「關閉」。我不想爲整個服務器做這個,只是這個特定的資源。通常情況下,您可以使用PHP腳本中的ini_set,但無論出於何種原因,php不允許以這種方式設置output_buffering(請參閱the php manual)。

事實證明,如果您使用Apache,您可以從服務器配置中設置一些php ini指令(包括output_buffering),包括.htaccess文件。所以我用的.htaccess中禁用output_buffering只是一個文件:

<Files "q.php"> 
    php_value output_buffering Off 
</Files> 

然後在我的靜態服務器的配置,我只是需要AllowOverride Options=php_value(或更大的錘子,就像AllowOverride All)爲了爲了在.htaccess文件中允許。

+1

不知道這是否總是錯誤或PHP5.6中的某些內容發生了變化,但我不得不使用'php_flag output_buffering Off'來使'Off'工作。 – RiggsFolly 2015-09-18 14:19:35

+0

我將php.ini中的「output_buffering」從4096設置爲Off,並重新引導整個服務器,並使用phpinfo()進行了驗證;但我仍然面臨同樣的問題,服務器在向瀏覽器發送數據之前正在等待頁面加載。 Apache2或Ubuntu 16.04中還有其他設置嗎?我正在使用PHP7。 – Tarik 2017-08-06 11:58:59

3

你沒有提到你正在使用的是什麼Web服務器,但我會在這裏出現一個肢體並猜測Apache2。我幾乎碰到了你描述的同樣的東西。我試圖讓我的CGI腳本傳回信息,因爲它已經準備好了,而不是緩衝整個事情。在捲曲等工作jiffy,但緩衝在瀏覽器(幾乎任何瀏覽器),這至少是瘋了。我經歷了你描述的確切步驟。在我的情況下,分辨率是修改sites-enabled/terrifico.com配置文件中的Apache2(有問題的符合

SetEnvIfNoCase開始

(您可以忽略的上方,線下的東西,我只是展示它在那裏我把它的參考。)

<VirtualHost *:80> 
ServerAdmin [email protected] 
ServerName test.terrifico.com 
ServerAlias test.terrifico.com 

SetEnvIfNoCase Request_URI \.cgi$ no-gzip dont-vary 

DocumentRoot /var/www/test.terrifico.com 

從盯着網絡流量來回,終於醒悟過來了,在瀏覽器中的廣告,它接受了通貨緊縮的任何東西(這是文本)。例如,這就是瀏覽器和curl之間的區別。其顯着位是

接受編碼:gzip,緊縮,SDCH

有一些關於chunking,但是這並沒有影響到這方面的問題。所以,瀏覽器請求mod_deflate啓動,這使我在我的CGI腳本中獲得它們時仔細剔除了字節。您可以在瀏覽器中更改它,但在作品中將其更改爲服務器似乎更明智。

也許這有助於。

2

要在運行時關閉PHP輸出緩衝而不更改php.ini或具有.htaccess文件,只需在腳本的開頭使用ob_end_flush()ob_end_clean()。例如:

這應該沒有緩衝輸出:

<?php 
ob_end_clean(); 

for ($i = 0; $i < 5; $i++) 
{ 
    echo "$i\n"; 
    flush(); 
    usleep(0.5e6); 
} 

此輸出具有緩衝(所有在同一時間)如果output_buffering是上,而不管flush()呼叫的:

<?php 

for ($i = 0; $i < 5; $i++) 
{ 
    echo "$i\n"; 
    flush(); 
    usleep(0.5e6); 
} 

儘管它名稱,ob_implicit_flush調用flush(),而不是ob_flush(),隱含在每個輸出之後。在開始關閉輸出緩衝區之後,在這種情況下可以得心應手:

<?php 
ob_end_clean(); // disable output buffer 
ob_implicit_flush(); // call flush() automatically after every output 

for ($i = 0; $i < 5; $i++) 
{ 
    echo "$i\n"; 
    usleep(0.5e6); 
} 

這修復了PHP方面的問題。 mod_deflate或其他類似情況可能會有其他情況(請參閱Ted Collins的答案),並且我發現Firefox在開始輸出任何內容之前至少需要1024個字節。

+0

此代碼確實是3x相同 - .- – 2017-09-01 08:47:57