問題是,對於一個漫長的過程,無論客戶端瀏覽器當前是否連接,PHP腳本都會繼續執行。有沒有可能,如果客戶端已經終止了對腳本的Ajax調用,那麼腳本也會在服務器上終止?我發現這是處理這個超時問題最簡單的辦法如果HTTP請求被取消/關閉,PHP會自動終止腳本
回答
正如指出的@metadings PHP確實有一個函數來檢查是否存在名爲connection_aborted連接中止()。它將返回1,如果連接否則爲0
終止在一個長長的服務器端程序,用戶可能需要知道,如果客戶端 從服務器斷開或者他已經關閉了瀏覽器,則 服務器可以安全地關閉該過程。
尤其是在應用程序使用php會話的情況下,如果我們在客戶端斷開連接後仍然運行長進程,那麼服務器將無法響應此會話。並且來自同一客戶端的任何其他請求將等到先前的進程完全執行。造成這種情況的原因是會話文件在進程運行時被鎖定。然而,你可以通過調用session_write_close()方法來解鎖它。但是這在所有情況下都不可行,可能需要在流程結束時寫入會話。
現在,如果我們只在一個循環中調用connection_aborted(),那麼它總是會返回0,無論連接是否關閉。
0意味着連接不中止。這是誤導。但是,經過重新搜索和實驗後,如果發現輸出緩衝區中的是php的原因。
首先,爲了檢查中止,循環中的開發人員必須通過回顯一些文本向客戶端發送一些輸出。例如:
print " ";
由於進程仍在運行,輸出將不會發送到客戶端。現在發送輸出,然後我們需要刷新輸出緩衝區。
flush();
ob_flush();
然後,如果我們檢查中止,那麼它會給出正確的結果。
if (connection_aborted() != 0) {
die();
}
以下是工作的例子,這會即使您正在使用PHP會議的工作:
session_start();
ignore_user_abort (TRUE);
file_put_contents ("con-status.txt", "Process started..\n\n");
for($i = 1; $i <= 15; $i ++) {
print " ";
file_put_contents ("con-status.txt", "Running process unit $i \n", FILE_APPEND);
sleep (1);
// Send output to client
flush();
ob_flush();
// Check for connection abort
if (connection_aborted() != 0) {
file_put_contents ("con-status.txt", "\nUser terminated the process", FILE_APPEND);
die();
}
}
file_put_contents ("con-status.txt", "\nAll units completed.", FILE_APPEND);
EDIT 07-APR-2017
如果有人使用快速-Cgi在Windows上,然後他實際上可以終止 CGI線程從內存中斷連接時使用以下代碼:
if (connection_aborted() != 0) { apache_child_terminate(); exit; }
請注意,'ob_flush'應該在'flush'前調用,如果輸出緩衝正在使用中(甚至可能是ob_end_flush?)http://stackoverflow.com/questions/4191385/php-buffer-ob-flush-vs-flush – metadings 2013-07-24 04:04:48
一種方法是這樣:
1:服務器爲「處理」上設置的值。開始一個獨立的線程來處理。
2:初始ajax調用返回成功
3:頁面上的javascript進入'等待模式',每10或30或60秒或5或10分鐘或其他任何事情發送新的ajax請求(取決於您的情況)來確定服務器上的值是否仍然設置爲'處理'。
4:獨立線程完成。它將服務器上的值設置爲「完成」。
5:頁面上的javascript進行下一個等待模式查詢,並返回'完成'和相應的數據。
4B:如果時間淫穢量的推移沒有「完成」時,它註冊爲失敗。多少時間是淫穢取決於你的情況。發送ajax調用,將值從'處理'更新爲'取消'。 5b:獨立線程定期檢查狀態以確保它仍然被設置爲'正在處理'。如果它看到模式轉換爲「取消」,它將自行取消。
這是你在找什麼: http://php.net/manual/en/function.ignore-user-abort.php
在執行過程中停止腳本可能會導致意想不到的結果,所以買者自負
退房PHP connection_aborted()函數。在進行處理時,您可以檢查中止的連接以正常取消進度,就像人們在交互式線程模型中所做的那樣。
哇。我甚至不知道這是在那裏。謝謝! – 2013-05-13 14:52:37
@metadings這似乎不適用於Ajax請求。 ajax請求被終止,並且connection_aborted()仍然返回0.即使我已經通過關閉網頁仍嘗試執行腳本。可能是什麼原因? – 2013-05-13 19:15:06
@metadings函數connection_aborted()有一個錯誤,它會一直返回0看到這個bug:https://bugs.php.net/bug.php?id=54062 ...有沒有其他的選擇? – 2013-05-13 19:34:12
- 1. HTTP請求不會關閉
- 2. 請求被中止:請求被取消
- 3. 如果腳本被取消,如何終止從Ant任務啓動的進程?
- 4. 當我關閉瀏覽器時,PHP腳本會終止嗎?
- 5. 如何在PHP腳本中確定Ajax請求被取消
- 6. 取消HTTP請求
- 7. 使用http獲取請求終止的線程終止
- 8. 如何取消http請求?
- 9. 」請求被中止:請求被取消。「同時處理PayPal IPN
- 10. HttpWebRequest:請求被中止:請求被取消
- 11. HTTP腳本請求「中止」狀態
- 12. Ajax http請求關閉
- 13. paypal Rest Api錯誤請求被中止:請求被取消。直到寫入所有字節才能關閉流
- 14. 自動取消jqgrid請求
- 15. 自動取消jqGrid請求
- 16. Python腳本自動關閉
- 17. 停止處理被終止的請求
- 18. 用於HTTP POST請求的PHP腳本
- 19. 關閉和/或終止php腳本中的mysqli連接?
- 20. 來自Adobe InDesign腳本的HTTP請求?
- 21. 來自Chrome擴展程序的HTTP發佈請求被取消
- 22. System.Net.WebException:請求已中止:請求已被取消
- 23. TFS簽入請求已中止:請求已被取消
- 24. HttpWebRequest的:請求已中止:請求已被取消
- 25. 取消$ http請求angularjs
- 26. Curl - 7.21.5 HTTP請求取消
- 27. Flash - 動作腳本2 - HTTP請求
- 28. 關閉窗口停止php腳本?
- 29. 打開進程終止時文件會自動關閉
- 30. 一個AJAX HTTP請求終止在Drupal
其中的困難是,一個新的AJAX調用必須到服務器上,這涉及到運行第二個PHP腳本來進行。第二個PHP腳本需要訪問由第一個PHP腳本生成的線程。我可以想到多種方式來做到這一點 - 但它不會是自動的。您需要確保編寫您的PHP代碼,以便通過新的獨立創建的線程以某種方式訪問或控制原始線程。 – 2013-05-13 14:17:54
實際上,PHP的默認行爲是在客戶端斷開連接時中止進程。 – Jon 2013-05-16 16:39:10
@jon在我的Windows服務器的情況下,它斷開連接後繼續運行。不過,我也不希望PHP僅僅關閉這個過程。我需要ROLLBACK數據庫事務並安全地關閉它。 – 2013-05-16 16:43:46