我所經曆的大檔案資料匯出(後台執行,自動產生),資料匯出自動產生_PHP教程

來源:互聯網
上載者:User

我所經曆的大檔案資料匯出(後台執行,自動產生),資料匯出自動產生


一、前言

記錄一下以前做的後台excel格式匯出統計資訊的功能,也是最近同事問到了相關東西,一時之間竟忘了具體的細節,因此記錄一下;

大家知道,excel匯出資料的功能,後台幾乎是必須功能,一般都是點擊後,組建檔案然後自動下載,

如果是資料量小的話,一下子便可請求完成,從而下載到本地;

但是,如果資料量特別大的時候,頁面就必須一直在等待,直到寫入excel成功,

這樣便影響了後台使用者無法操作其他頁面,為此,對excel匯出做了以下功能最佳化:


二、產生excel檔案

產生excel檔案的方法有很多,暫不一一記錄,只是記錄本次的方法;

這裡用到了table的html格式,以及相應的excel的聲明

(隱約記得其他的方法用office07開啟的時候好像是亂碼,後面嘗試用csv格式檔案,可還是亂碼,所以用了table的形式)

檔案的開頭:

1 $struserdata = <<<Eof 2 3 xmlns:x="urn:schemas-microsoft-com:office:excel" 4 xmlns="http://www.w3.org/TR/REC-html40"> 5 6 PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 7 8 9 10 12 13 14 15 16 17View Code

檔案的結尾:

1 $struserdata = <<<Eof2 Eof;
3 4 5 6 Eof;
View Code

當然,檔案中間就是一些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;

思路:


查看檔案的進度方法:

1 public function execscript_process(){ 2 $this->load->library('smarty'); 3 $file_arr_str = array(); 4 $file_arr_process = array(); 5 $file_arr_name = array(); 6 $file_arr = array(); 7 $refresh_flag = 'yes'; 8 $uid = $_REQUEST['uid']; 9 $url_dir = STATISTIC_EXPORT_FILE_DIR.$uid .'/';//@todo10 if(!is_dir($url_dir)){11 @mkdir($url_dir,0777);12 }13 $files = scandir($url_dir);14 15 if(!empty($files)){16 foreach ($files as $key => $value) {17 if($value!='.' && $value!='..'){18 if(substr($value, 0 , 5)=="flag_"){19 $file_size = filesize($url_dir . $value);20 if(!empty($file_size)){21 $fhandle = fopen($url_dir . $value, 'rb+');22 fseek($fhandle, -1, SEEK_END);23 $fstr = '';24 while(($c = fgetc($fhandle)) !== false) {25 if($c == "\n" && $fstr) break;26 $fstr = $c . $fstr;27 fseek($fhandle, -2, SEEK_CUR);28 }29 fclose($fhandle);30 $fstr = trim($fstr);31 $fstr_arr_str = explode(',', $fstr);32 $file_arr_process[] = 100 * number_format($fstr_arr_str[0]/$fstr_arr_str[1],2).'%';33 $file_arr_name[] = substr($value,5);34 }35 }36 }37 }38 39 foreach ($file_arr_process as $key => $value) {40 if($value != '100%'){41 $refresh_flag = 'no';42 break;43 }44 }45 }46 47 $file_arr = array(48 'process' => $file_arr_process,49 'name' => $file_arr_name,50 'refresh_flag' => $refresh_flag51 );52 $file_arr_json = json_encode($file_arr);53 echo $file_arr_json;54 }View Code

五、下載檔案

檔案的下載就好說了,既然已經都產生成功,下載的方法如下:

 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/4636457http://www.codesky.net/article/201202/163385.htmlhttp://www.cnblogs.com/zdz8207/p/3765567.htmlhttp://blog.163.com/mojian20040228@126/blog/static/4112219320097300922992/http://php.net/manual/en/features.commandline.phphttp://blog.csdn.net/yangjun07167/article/details/5603425http://blog.csdn.net/yunsongice/article/details/5445448http://www.cppblog.com/amazon/archive/2011/12/01/161281.aspxhttp://blog.51yip.com/tag/proc_openhttp://www.justwinit.cn/post/1418/http://limboy.me/tech/2010/12/05/php-async.html

http://www.bkjia.com/PHPjc/1048777.htmlwww.bkjia.comtruehttp://www.bkjia.com/PHPjc/1048777.htmlTechArticle我所經曆的大檔案資料匯出(後台執行,自動產生),資料匯出自動產生 一、前言 記錄一下以前做的後台excel格式匯出統計資訊的功能,也...

  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.