有兩個頁面一個上傳EXCEL檔案,另一個接受這個EXCEL檔案並處理,下面是這個頁面處理時顯示的內容,可是每次都要等程式完全運行才會顯示。有時候時間太長沒有反饋,使用者會關閉頁面,我想增加即時提示。求大家指點下
我想過用非同步方法,可第二個檔案是在Ifram架構內的,非同步擷取也是要等待值的,最終顯示還是一樣。
//117條資料讀取插入並且產生報表11:04:17 開始讀取EXCEL表。11:04:31 讀取並插入資料庫成功11:04:31 完成活頁簿添加一個工作表。11:04:32 完成工作表內容寫入。11:04:32 完成工作表複製。11:04:32 完成複製工作表【失業】添加。11:04:33 完成工作表複製。11:04:33 完成複製工作表【醫學】添加。11:04:33 完成工作表複製。11:04:33 完成複製工作表【工傷】添加。11:04:34 完成工作表複製。11:04:34 完成複製工作表【生育】添加。11:04:34 完成工作表複製。11:04:34 完成複製工作表【重大疾病】添加。11:04:35 完成工作表複製。11:04:35 完成複製工作表【補充醫學】添加。11:04:35 設定檔案基本資料。11:04:35 查詢結果集資料庫成功。11:04:35 查詢結果集轉化為數組成功。11:04:35 完成活頁簿[養老]資料填入。11:04:36 完成活頁簿[失業]資料填入。11:04:36 完成活頁簿[醫學]資料填入。11:04:36 完成活頁簿[工傷]資料填入。11:04:37 完成活頁簿[生育]資料填入。11:04:37 完成活頁簿[重大疾病]資料填入。11:04:38 完成活頁簿[補充醫學]資料填入。11:04:46 完成活頁簿檔案創立。
回複內容:
有兩個頁面一個上傳EXCEL檔案,另一個接受這個EXCEL檔案並處理,下面是這個頁面處理時顯示的內容,可是每次都要等程式完全運行才會顯示。有時候時間太長沒有反饋,使用者會關閉頁面,我想增加即時提示。求大家指點下
我想過用非同步方法,可第二個檔案是在Ifram架構內的,非同步擷取也是要等待值的,最終顯示還是一樣。
//117條資料讀取插入並且產生報表11:04:17 開始讀取EXCEL表。11:04:31 讀取並插入資料庫成功11:04:31 完成活頁簿添加一個工作表。11:04:32 完成工作表內容寫入。11:04:32 完成工作表複製。11:04:32 完成複製工作表【失業】添加。11:04:33 完成工作表複製。11:04:33 完成複製工作表【醫學】添加。11:04:33 完成工作表複製。11:04:33 完成複製工作表【工傷】添加。11:04:34 完成工作表複製。11:04:34 完成複製工作表【生育】添加。11:04:34 完成工作表複製。11:04:34 完成複製工作表【重大疾病】添加。11:04:35 完成工作表複製。11:04:35 完成複製工作表【補充醫學】添加。11:04:35 設定檔案基本資料。11:04:35 查詢結果集資料庫成功。11:04:35 查詢結果集轉化為數組成功。11:04:35 完成活頁簿[養老]資料填入。11:04:36 完成活頁簿[失業]資料填入。11:04:36 完成活頁簿[醫學]資料填入。11:04:36 完成活頁簿[工傷]資料填入。11:04:37 完成活頁簿[生育]資料填入。11:04:37 完成活頁簿[重大疾病]資料填入。11:04:38 完成活頁簿[補充醫學]資料填入。11:04:46 完成活頁簿檔案創立。
非常感謝大家的回答,我用的是提交頁面控制一個進度條,按下按鈕進度條開始啟用,設定一個大於使用者完成操作的時間,當另一個頁面處理完成時,計算出這個進度條未布滿的部門,用額外5S 控制進度條速度填滿
function flush_buffers(){ ob_end_flush(); ob_flush(); flush(); ob_start('ob_callback');}function ob_callback($buffer){ return $buffer . str_repeat(' ', max(0, 4097 - strlen($buffer)));}
demo
echo '
處理1!
';flush_buffers();//do ....echo '
處理2!
';flush_buffers();
拓展:
PHP5.4上傳進度支援(Upload progress in sessions)
題主問的應該是即時輸出
的問題,一般情況下一個php指令碼在全部執行完畢後,才會將指令碼輸出一次性返回,而在執行過程中的輸出內容是沒有辦法即時擷取的,這種行為叫輸出緩衝
,可以通過output.buffering
(PHP手冊)來開關
訪問這個頁面,會在header內容
全部輸出1秒
後,同時
輸出12
但在程式中可以通過flush
強制將緩衝內容輸出並清空緩衝
加上flush之後,一般情況下
,1
會在header
返回後立即輸出
,1秒之後,再輸出2
。
為什麼是一般情況下
呢,因為php的緩衝是重新整理了,但是如果前端web伺服器(如apache)開啟了gzip/deflate/cache等需要等待指令碼輸出完畢才能執行
的功能,會被再一次緩衝
。
如果真的需要這樣的即時輸出
功能,需要把整個response鏈路上所有的緩衝功能全部關閉,其實是有些得不償失的~
http://php.net/manual/zh/function.flush.php
我能想到的有兩種辦法,都是用AJAX非同步:
將每一個步驟都分成一個函數然後URL傳參執行對應函數,比如step=first
對應運行first()
函數,運行成功返回你的內容。前端這邊用AJAX請求,如果成功返回則append
內容到頁面上然後再繼續請求下一步這樣一直遞迴下去直至任務完成。可以參考我給Typecho寫的線上升級外掛程式,使用的就是這種方法。
這種方法就比較簡單了PHP每次運行完一步就把內容append
到一個JSON檔案中,前端這邊用AJAX輪詢請求這個JSON檔案並顯示到頁面上。
上傳進度如 @宋小北 所說,鳥哥的部落格中說的很明確:
1、PHP5.4之前,APC通過apc.rfc1867_freq string
選項原生支援檔案上傳的緩衝更新,參考 http://php.net/manual/zh/apc.configuration.php#ini.apc.rfc1867
2、PECL也有擴充實現上傳進度 http://pecl.php.net/package/uploadprogress
如果你用較早版本,又不想搞上述勞什子,就用 Flash 上傳組件如swfupload或者jQuery File Upload之類。
上傳完成後即時顯示處理結果,你可以關閉Web Server 和 PHP的各種buffer,然後靠flush()
強制輸出。但這是一個愚蠢的做法。
給一個簡單思路,每處理一步就向第三方儲存比如memcached,redis,甚至是檔案裡寫入一個標記,通過ajax輪詢這個標記,准即時更新dom裡的內容。這應該是比較折衷比較理想的方案。恁看中不中?
====
@公子 老師指點了一下,我發現他的第一個方案把操作拆成幾步來做更好,處理大檔案時可以防止逾時。同時要注意很多問題,比如檔案狀態維護防止漏操作,每一步都要重複讀檔案等等...我只是吃飯前來SG逗個樂子,具體的細節還是題主自己考慮吧。
將程式放在隊列中處理,將執行日誌放到資料庫或者文本,然後通過ajax輪詢擷取和處理進度並顯示
我專門的寫了個解決方案的文章,去看看:http://segmentfault.com/a/1190000004235213