php不使用Office包實現上萬條資料匯出表格

悦~發表於2024-06-25

經過上傳客戶要求主副表遷出,又提出可以將某張表的資料匯出excel,聽著很簡單,實際看資料表發現上萬條資料,並且需要關聯表查詢相關欄位,匯出的表格才可以被客戶看明白。

要是使用office包目前後臺記憶體耗盡,被迫停止執行,所以想要突破百萬條資料匯出需要另闢它路。所以就是使用了匯出CSV並非excel檔案。

1、設定程式需要一直執行並設定執行記憶體(php提示過128M)by user 悅悅 https://www.cnblogs.com/nuanai

2、資料查詢出需要匯出的資料欄位(分頁)

3、分頁進行匯出檔案並一起合併成壓縮包後下載

如果匯出前需要某些條件篩選,那就需要在前端設定表單提交篩選條件(不過多介紹)

匯出配置的編寫,需要設定檔案路徑、名稱、表頭等基本資訊 by user 悅悅 https://www.cnblogs.com/nuanai

 1 //讓程式一直執行
 2 set_time_limit(0); 
 3 //設定程式執行記憶體---php提示過128M
 4 ini_set('memory_limit', '128M');
 5 //檔名使用的日期命名
 6 $fileName = date('YmdHis', time());
 7 //檔案儲存位置    
 8 $destPath = ROOT_PATH . 'public' .DS. 'uploads'.DS.'download'.DS.$fileName. '.csv';
 9 // 開啟檔案控制代碼,準備寫入資料  
10 $fileHandle = fopen($destPath, 'w');
11 // 檢查檔案控制代碼是否成功開啟  
12 if ($fileHandle === false) {
13     die('無法開啟檔案: ' . $fileHandle);
14 }
15 //表頭
16 fputcsv($fileHandle,['序號', '產品名稱', '產品型號','工名稱','條碼1','條碼2','狀態','時間']);
17 //條數
18 $nums = 10000;
19 //資料表的總數
20 $count = $this->model->count();
21 $step = ceil($count/$nums);

查詢資料,這邊需要關聯表查詢用的是左查詢的方式,透過for迴圈進行每頁的寫入檔案

時間戳格式化直接使用了sql語句轉換,省去進入迴圈後再次迴圈格式化 by user 悅悅 https://www.cnblogs.com/nuanai

1 FROM_UNIXTIME(updatetime, '%Y-%m-%d %H:%i:%s')

需要注意就是寫入CSV之前需要對欄位轉一維陣列

 1 for($i=0;$i<$step;$i++){
 2     $start = $i*$nums;
 3     $result = $this->model->alias('pd')
 4         ->join('products ps','ps.id=pd.product_id','LEFT')
 5         ->join('step st','st.id=pd.step_id','LEFT')
 6         ->field("pd.id,ps.name,ps.spec,st.name as sname,pd.barcode,pd.barnum,pd.isin,FROM_UNIXTIME(pd.updatetime, '%Y-%m-%d %H:%i:%s') AS uptime")->order("pd.updatetime","desc")->limit($start,$nums)->select();
 7         
 8     foreach ($result as $K=> &$item) {
 9         // 轉換每行資料為一維陣列
10         $rowData = [
11             $item['id'],
12             $item['name'],
13             $item['spec'],
14             $item['sname'],
15             $item['barcode'],
16             $item['barnum'],
17             $item['isin'],
18             $item['uptime']
19         ];
20         
21         // 寫入 CSV
22         fputcsv($fileHandle, $rowData);
23     }
24     
25 }

開啟了檔案控制代碼,記得關閉

1 // 關閉檔案控制代碼 2 fclose($fileHandle);

到這裡就是可以將上萬條資料匯出CSV檔案了,為了減少客戶下載時間,又進行了對檔案壓縮,客戶下載壓縮檔案。 by user 悅悅 https://www.cnblogs.com/nuanai

這裡使用的呼叫方法,需要傳入引數:檔名

 1 if (!class_exists('ZipArchive')) {
 2     throw new Exception(__('ZinArchive not install'));
 3 }
 4 $downloadPath = ROOT_PATH . 'public' .DS. 'uploads'.DS.'download'.DS; //伺服器中檔案zip儲存的位置
 5 $destDir =  $downloadPath.$zipName . '.zip'; //全路徑
 6 $zip = new \ZipArchive;  //壓縮類
 7 $zip->open($destDir, \ZipArchive::CREATE | \ZipArchive::OVERWRITE);
 8 $csvDir = $downloadPath .$csvFileName.'.csv'; //需要壓縮檔案的全路徑
 9 $fileName = basename($csvDir); //獲取檔名
10 $zip->addFile($csvDir, $fileName);
11 $zip->close();
12 $zipFilename = basename($destDir);
13 // 設定HTTP頭資訊  
14 header('Content-Type: application/octet-stream');  
15 header('Content-Disposition: attachment; filename="'.$zipFilename.'"');  
16 header('Content-Length: ' . filesize($destDir));
17 // 讀取並輸出ZIP檔案內容  
18 readfile($destDir);
19 // 刪除臨時ZIP檔案(可選)  
20 unlink($destDir);

這邊再生成壓縮檔案後,並刪除了雲伺服器中的壓縮檔案,如果伺服器空間允許看個人選擇;如果想要刪除伺服器中的CSV檔案,需要在生成壓縮檔案後進行刪除操作

在第一個方法的最後新增如下程式碼:儲存檔案的路徑 by user 悅悅 https://www.cnblogs.com/nuanai

1 unlink($destPath);

到這裡就可以實現客戶透過後臺進行上萬條資料的匯出下載功能了,就是有一個弊端,需要等待瀏覽器跳出下載框,哎,給客戶說一下耐心生成檔案吧。

相關文章