我有ob_start()
和相應的ob_flush()
。我想刷新一部分數據並繼續執行其餘部分。使用ob_flush()
沒有幫助。如果可能的話,還需要在瀏覽器中顯示加載而不顯示。如何刷新數據到瀏覽器,但繼續執行
編輯:
我不想用ajax
我有ob_start()
和相應的ob_flush()
。我想刷新一部分數據並繼續執行其餘部分。使用ob_flush()
沒有幫助。如果可能的話,還需要在瀏覽器中顯示加載而不顯示。如何刷新數據到瀏覽器,但繼續執行
編輯:
我不想用ajax
ob_flush
寫入緩衝區。換句話說,ob_flush
告訴PHP給Apache(或nginx/lighttpd/whatever)輸出,然後讓PHP忘記它。一旦Apache有輸出,它就可以隨心所欲地執行任何操作。 (換句話說,在ob_flush
之後,不管它是否立即寫入瀏覽器,都無法控制)。
所以,簡短的回答:沒有保證的方式來做到這一點。
只是猜測,你可能正在尋找AJAX。每當有人在頁面內容加載時嘗試操作,AJAX幾乎總是正確的路徑。
如果您想在後臺繼續執行任務,則可以使用ignore_user_abort
,但詳細的here,但這通常不是最佳方法。你基本上失去了對該線程的控制,並且在我看來,Web服務器線程並不是重處理所屬的地方。
我會嘗試從面向網絡的東西中提取出來。這可能意味着一個cron條目或者只是從PHP內部產生一個後臺進程(一個從腳本執行內部啓動的進程不會因爲腳本而死亡,並且腳本不會在死前完成)。
如果你確實走了那條路,這意味着你甚至可以根據需要製作某種狀態系統。然後,您可以監視執行情況,併爲用戶定期更新進度。 (從技術上講,你也可以使用ignore_user_abort
-ed腳本製作狀態系統,但它對我來說似乎並不那麼幹淨。)
當新用戶登錄時,我想節省很多數據。這些數據應該立即保存,但不會中斷用戶,即在瀏覽器上顯示加載 – aWebDeveloper
我有一篇文章解釋瞭如何在我的博客上使用apache/mod_php來實現這一點:http://codehackit.blogspot.com/2011/07/how-to-kill-http-connection-and.html希望這有助於歡呼
如果您在此處添加了一小段代碼,這將對您有所幫助,因此如果您的網站出現故障,我們仍然可以在此處找到答案。你在你的博文中寫的代碼有效。但是,如果您之前告訴apache gzip您的內容,它將不再有效(因爲長度將不再正確) – Zombaya
用途:
header("Content-Length: $len");
..where $len
是數據的長度刷新到客戶端。
我沒有背景,知道何時何這是去工作,但我想在幾個瀏覽器,並且所有立刻回到:
<?PHP
header("Content-length:5");
echo "this is more than 5";
sleep(5);
?>
編輯:瀏覽器,IE瀏覽器,並Opera顯示this
,而FireFox顯示this is more than 5
。儘管如此,他們都關閉了請求。
這就是爲什麼內容長度需要與實際內容長度相同的原因。謹防gzip,因爲這會改變你的回覆的長度。 – Zombaya
@ Zombaya,我不明白這是如何相關的。只要他沒有試圖在一定量之後切斷他的輸出,就應該在發送必要的數據後結束請求。 – mowwwalker
那麼,當我嘗試這樣做,並且長度與實際長度不匹配時,連接不會總是關閉並繼續加載。 – Zombaya
我在過去做到了這一點,這是我如何解決它:
ob_start();
/*
* Generate your output here
*/
// Ignore connection-closing by the client/user
ignore_user_abort(true);
// Set your timelimit to a length long enough for your script to run,
// but not so long it will bog down your server in case multiple versions run
// or this script get's in an endless loop.
if (
!ini_get('safe_mode')
&& strpos(ini_get('disable_functions'), 'set_time_limit') === FALSE
){
set_time_limit(60);
}
// Get your output and send it to the client
$content = ob_get_contents(); // Get the content of the output buffer
ob_end_clean(); // Close current output buffer
$len = strlen($content); // Get the length
header('Connection: close'); // Tell the client to close connection
header("Content-Length: $len"); // Close connection after $len characters
echo $content; // Output content
flush(); // Force php-output-cache to flush to browser.
// See caveats below.
// Optional: kill all other output buffering
while (ob_get_level() > 0) {
ob_end_clean();
}
正如我在一對夫婦的意見之前說的,你應該注意使用gzip壓縮您的內容,因爲這將改變你的內容的長度,但不改變它的標題。它也可以緩衝你的輸出,所以它不會立即發送給客戶端。
你可以試着讓apache知道不使用apache_setenv('no-gzip', '1');
來gzip你的內容。但是如果你使用rewrite-rules進入你的頁面,這將不起作用,因爲那樣它也會修改這些環境變量。至少,它是爲我做的。
查看更多關於將您的內容刷新到manual中的用戶的警告。
只是一個FYI的PHP函數是ob_get_content ** S ** –
發現故意的錯誤。 $ len!= $ size; –
@LukeOliff,謝謝你的提醒,改變了它。 – Zombaya
這是我的功能
function bg_process($fn, $arr) {
$call = function($fn, $arr){
header('Connection: close');
header('Content-length: '.ob_get_length());
ob_flush();
flush();
call_user_func_array($fn, $arr);
};
register_shutdown_function($call, $fn, $arr);
}
包到底要執行的功能,PHP後關閉連接。當然瀏覽器會停止緩衝。
function test() {
while (true) {
echo 'this text will never seen by user';
}
}
這是如何調用該函數
bg_process('test');
第一個參數是callable
, 第二個參數是一個數組要傳遞給「測試」功能與索引數組
注:在腳本開始處我不使用ob_start()
。
做完第一個ob_flush後,是否需要顯示其他輸出?或者您希望客戶完全瞭解請求,然後在後臺繼續進行某些處理? – Corbin
繼續在後臺 – aWebDeveloper
好的,已經更新了我的答案。 – Corbin