所經歷的大檔案資料匯出(後臺執行,自動生成)
所經歷的大檔案資料匯出(後臺執行,自動生成)
http://www.cnblogs.com/fanfan259/p/4710019.html
一、前言
記錄一下以前做的後臺excel格式匯出統計資訊的功能,也是最近同事問到了相關東西,一時之間竟忘了具體的細節,因此記錄一下;
大家知道,excel匯出資料的功能,後臺幾乎是必須功能,一般都是點選後,生成檔案然後自動下載,
如果是資料量小的話,一下子便可請求完成,從而下載到本地;
但是,如果資料量特別大的時候,頁面就必須一直在等待,直到寫入excel成功,
這樣便影響了後臺使用者無法操作其他頁面,為此,對excel匯出做了以下功能優化:
- excel匯出分成兩部分內容:生成excel檔案和下載excel檔案
- excel的檔案生成在程式後臺執行,前端不必等待,可進行其他後臺操作
- 增加下載檔案頁面,顯示excel檔案生成的進度,完成後,方可下載生成的excel檔案
- 檔案生成後,點選下載方可下載相應的檔案
二、生成excel檔案
生成excel檔案的方法有很多,暫不一一記錄,只是記錄本次的方法;
這裡用到了table的html格式,以及相應的excel的宣告
(隱約記得其他的方法用office07開啟的時候好像是亂碼,後面嘗試用csv格式檔案,可還是亂碼,所以用了table的形式)
檔案的開頭:
1 $struserdata = <<<Eof 2 <html xmlns:o="urn:schemas-microsoft-com:office:office" 3 xmlns:x="urn:schemas-microsoft-com:office:excel" 4 xmlns="http://www.w3.org/TR/REC-html40"> 5 6 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 7 <html> 8 <head> 9 <meta http-equiv="Content-type" content="text/html;charset=utf-8" /> 10 <style id="Classeur1_16681_Styles"> 11 </style> 12 </head> 13 <body> 14 <div id="Classeur1_16681" align=center x:publishsource="Excel"> 15 16 <table x:str border=1 cellpadding=0 cellspacing=0 width=100% style=`border-collapse: collapse`> 17 Eof;
檔案的結尾:
1 $struserdata = <<<Eof 2 </table> 3 </div> 4 </body> 5 </html> 6 Eof;
當然,檔案中間就是一些tr td 標籤了。
三、讓程式在後臺執行
場景:
使用者點選 生成excel後,跳轉到下載頁面,程式在後臺執行,使用者可不必等待生成完成,可執行其他操作;
下載頁面可看到檔案生成的進度以及是否可下載狀態
思路:
點選 生成excel,顯示下載頁面 —> show_download方法
生成excel —> create_excel 方法
show_download方法中呼叫 create_excel方法,而show_download 方法中,自己用了一下命令列執行程式的方式,
利用php命令列的方式,把引數傳遞給 create_excel方法
1 // $cmd = "/usr/bin/php /home/xxx/xxx.php " . $strjoin . " >/dev/null & "; 2 // $a=exec($cmd, $out, $returndata); 3 4 5 $command = "/usr/bin/php ".STATISTIC_EXPORT_SCRIPT_DIR."xxx.php " . "`" .$strjoin ."`". " " . $uid . " ". $action ." & "; 6 $process = proc_open($command, array(),$pipes); 7 $var = proc_get_status($process); 8 proc_close($process); 9 $pid = intval($var[`pid`])+1;
而在create_excel方法中:
需填寫以下程式碼:
1 set_time_limit(0); //取消指令碼執行時間的超時上限 2 3 ignore_user_abort(TRUE); //後臺執行,不受使用者關閉瀏覽器的影響
呼叫相關的api得到資料:
1 $statistic = call_user_func(array(`shellscript`,`get_result`),$url,$params); 2 if(!is_object($statistic) || !isset($statistic->data->items)){ 3 usleep(400000);//停止400毫秒 4 $statistic = call_user_func(array(`shellscript`,`get_result`),$url,$params); 5 }
四、顯示檔案生成進度
但是怎麼顯示相應的檔案生成進度呢,怎麼知道檔案到底生成好了沒有呢?
這裡,我用到的方法是,在寫入資料檔案的時候data.xsl,每個資料檔案都生成一個對應的檔案進度檔案,暫且稱為flag_data.xsl;
思路:
- 第一次請求api的時候,根據返回的total總數,以及pagesize,確定要請求的次數count;
- 這樣便可知道要請求api的次數(分頁請求api),在寫入資料檔案的同時,同時寫入進度檔案flag_data.xsl;
資料格式大約是(以逗號分割)
1,5
2,5
…- 然後顯示檔案進度的時候,讀取進度檔案,這樣變可知道資料檔案大體的進度
- 前端js處理時,幾秒讀取一次相應的方法(如果都100%進度,可停止請求方法),從而實現動態檢視檔案的生成進度
檢視檔案的進度方法:
五、下載檔案
檔案的下載就好說了,既然已經都生成成功,下載的方法如下:
1 public function execscript_download(){ 2 $filename = $_REQUEST[`filename`]; 3 $uid = $_REQUEST[`uid`]; 4 $file_dir = STATISTIC_EXPORT_FILE_DIR.$uid.`/`.$filename; 5 if (!file_exists($file_dir)){ 6 header("Content-type: text/html; charset=utf-8"); 7 echo "File not found!"; 8 exit; 9 } else { 10 ini_set("memory_limit","500M"); 11 header(`Content-Description: File Transfer`); 12 header(`Content-Type: application/octet-stream`); 13 header(`Content-Disposition: attachment; filename=`.basename($file_dir)); 14 header(`Content-Transfer-Encoding: binary`); 15 header(`Expires: ` . gmdate(`D, d M Y H:i:s`) . ` GMT`); 16 header(`Cache-Control: must-revalidate,post-check=0, pre-check=0`); 17 header(`Pragma: public`); 18 header(`Content-Length: ` . filesize($file_dir)); 19 readfile($file_dir); 20 } 21 22 }
六、上線後出現的問題
本地本來已經測試完畢,可上線後,卻出現了奇怪的問題;
現象描述:
當在後臺點選生成檔案,跳轉到下載頁的時候,因為下載頁是顯示檔案進度的頁面,
竟然出現有時候有剛剛點選的檔案進度,有時候沒有,就感覺沒有生成相應的檔案一樣;解決方法:
因為資料檔案和進度檔案都是生成在程式的某個資料夾file中,所以讀取的時候都是讀取的資料夾下的檔案,從而判斷顯示進度;
後面才知道,由於後臺程式有兩臺伺服器,導致讀取以及下載的時候找不到相應的資料夾,兩個伺服器相應的資料夾弄個共享目錄就可以了
七、相應的後續優化
由於下載的檔案多了,導致資料夾下的檔案越來越多,而原來生成的檔案是沒有價值的,所以加了個定期刪除檔案的功能,只保留近七天的檔案
當然可以用crontab,只不過我比較懶,是在點選生成檔案的時候,判斷了一下資料夾中的過期檔案,從而刪除
1 public function execscript_process_show(){ 2 $this->load->library(`smarty`); 3 $uid = $_REQUEST[`uid`]; 4 $url_dir = STATISTIC_EXPORT_FILE_DIR.$uid .`/`;//@todo 5 if(!is_dir($url_dir)){ 6 @mkdir($url_dir,0777); 7 } 8 $files = scandir($url_dir); 9 if(!empty($files)){ 10 foreach ($files as $key => $value) { 11 if($value!=`.` && $value!=`..`){ 12 foreach ($files as $key => $value) { 13 if($value!=`.` && $value!=`..`){ 14 if(substr($value, 0 , 5)!="flag_"){ 15 $filenamedate = substr($value, 0,10); 16 $today = date(`Y-m-d`,time()); 17 $filenamedate = date(`Y-m-d`,strtotime($filenamedate)+(STATISTIC_FILE_EXPIRE_DAY-1)*24*3600); 18 if($today>$filenamedate){//檔案過期 19 @unlink($url_dir . $value); 20 @unlink($url_dir . `flag_` . $value); 21 } 22 } 23 } 24 } 25 } 26 } 27 } 28 29 $this->smarty->assign(`uid`,$uid); 30 $this->smarty->display(`interact/statistic/execscript.tpl`); 31 }
八、後記
大檔案的匯出大體就是這個樣子,歡迎大家吐槽,共同交流;
當時在用命令列執行方法的時候,也參考了一下相應的資料,記錄一下;
http://blog.csdn.net/yysdsyl/article/details/4636457 http://www.codesky.net/article/201202/163385.html http://www.cnblogs.com/zdz8207/p/3765567.html http://blog.163.com/mojian20040228@126/blog/static/4112219320097300922992/ http://php.net/manual/en/features.commandline.php http://blog.csdn.net/yangjun07167/article/details/5603425 http://blog.csdn.net/yunsongice/article/details/5445448 http://www.cppblog.com/amazon/archive/2011/12/01/161281.aspx http://blog.51yip.com/tag/proc_open http://www.justwinit.cn/post/1418/ http://limboy.me/tech/2010/12/05/php-async.html
相關文章
- django實現將後臺資料excel檔案形式匯出DjangoExcel
- PHP 匯出大資料 CSV 檔案PHP大資料
- mysqldumper 多執行緒 匯出匯入資料MySql執行緒
- 批處理檔案 bat 後臺執行BAT
- 使用xml檔案,做資料的匯入,匯出 (轉)XML
- oracle 大檔案匯出方法Oracle
- 執行大資料量SQL檔案大資料SQL
- magento2 後臺資料展示+csv匯出
- php讀取excel檔案資料的匯入和匯出PHPExcel
- Linux scp 後臺執行傳輸檔案Linux
- [Docker核心之容器、資料庫檔案的匯入匯出、容器映象的匯入匯出]Docker資料庫
- 自動生成Mybatis的Mapper檔案MyBatisAPP
- 大資料開發-linux後臺執行,關閉,檢視後臺任務大資料Linux
- 如何檢測Windows服務停止後自動啟動?自動執行.bat批處理檔案?WindowsBAT
- oracle匯出資料到檔案中的方法 -- 轉自網路Oracle
- 如何獲取java執行時動態生成的class檔案?Java
- maven外掛執行過程中自動執行sql檔案MavenSQL
- MATLAB生成可執行檔案Matlab
- 刪除資料夾下SVN自動生成的檔案的一個bat方法BAT
- MySQL匯入匯出檔案檔案MySql
- 使用Mavne生成可以執行的jar檔案JAR
- 怎麼生成可執行的.jar檔案???????????JAR
- 遞迴遍歷磁碟下的某一資料夾中所有檔案,並copy檔案生成檔案和帶資料夾的檔案遞迴
- MSSQL資料庫後臺程式(執行緒)SQL資料庫執行緒
- Excel匯出 並完成後自動開啟Excel
- plsql developmer 匯出資料和生成資料SQLdev
- 大量包含Insert語句的指令碼檔案批量執行匯入資料指令碼
- 用impdp匯入資料的一次經歷
- 如何讓bat,cmd檔案後臺執行?如何把檔案打包成EXE?BAT
- 自動生成代替interface的執行緒安全map執行緒
- 一個java檔案被執行的歷程Java
- docker啟動的服務有匯出檔案的功能,檔案一直匯出失敗Docker
- oracle匯出大數量資料到檔案sqluldr2OracleSQL
- 自動生成檔案層級樹類
- 大資料使用Excel匯出大資料Excel
- matlab (.m)檔案生成 windows 可執行(.exe)檔案MatlabWindows
- Oracle 刪除資料後釋放資料檔案所佔磁碟空間Oracle
- ADB匯出app到電腦生成apk檔案APPAPK