1. 程式人生 > 其它 >PHP匯出百萬資料到Excel檔案

PHP匯出百萬資料到Excel檔案

匯出大容量的資料主要是因為持續佔用記憶體,系統容易崩潰,下面我用過的兩種辦法都可以

1.我們可以更改伺服器配置,找到以下幾個配置引數,讓他匯出的時候不會因為時間長掛掉

fastcgi_connect_timeout750000;#連結
fastcgi_read_timeout600000;#讀取
fastcgi_send_timeout600000;#發請求

2 就是在匯出過程中釋放我們的快取區

先封裝一個匯出類包 xlsTools.php (複製貼上一把梭)

<?php

/*這個是類包*/

class xlsTools{
    
    var $inEncode='utf-8';
    var $outEncode
='gb2312'; protected $rowCount; //儲存已經存在記憶體中的記錄條數 protected $rowFlushCount; // 一次flush的資料條數 public function __construct( $rowFlushCount = 1000 ) { $this->rowFlushCount = $rowFlushCount; $this->rowCount = 0; } public function __destruct() {
// TODO: Implement __destruct() method. } public function start($param){ // todo 檔名這裡建議允許自定 ddcoder $filename = $param['type'].'-'.date('YmdHis').'('.$param['name'].')'; $this->doStart($param['title'],$filename); } public function doStart($keys,$filename){
$this->download($filename.'.xls'); // php輸出到緩衝區 echo '<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><style>td{vnd.ms-excel.numberformat:@}</style></head>'; echo '<table width="100%" border="1">'; // 有時候需要自定義表頭 ddcdoer 修改於2017-08-26 if ( $keys ) { echo '<tr><th filter=all>'.implode('</th><th filter=all>',$keys)."</th></tr>\r\n"; } //重新整理緩衝區 ob_flush(); flush(); } //下載檔案 //$mimeType = 'application/force-download' //Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet //$mimeType = 'application/vnd.ms-excel' function download($fname = 'data', $data = null, $mimeType = 'application/force-download') { if (headers_sent($file, $line)) { echo 'Header already sent @ ' . $file . ':' . $line; exit(); } //header('Cache-Control: no-cache;must-revalidate'); // //fix ie download bug header('Pragma: no-cache, no-store'); header("Expires: Wed, 26 Feb 1997 08:21:57 GMT"); if (strpos($_SERVER["HTTP_USER_AGENT"], 'MSIE')) { $fname = urlencode($fname); header('Content-type: ' . $mimeType); } else { header('Content-type: ' . $mimeType . ';charset=utf-8'); } header("Content-Disposition: attachment; filename=\"" . $fname . '"'); //header( "Content-Description: File Transfer"); if ($data) { header('Content-Length: ' . strlen($data)); echo $data; exit(); } } public function csv_export($keys , $expData , $type , $count) { $csv = ''; foreach ($keys as $key){ $csv .= '"'.iconv("UTF-8", "gb2312",$key).'",'; } $csv .= "\n"; foreach($expData as $expArr) { foreach ($expArr as $e_key=>$exp){ $csv .= iconv("UTF-8", "gbk",$this->escapeCSV($expArr[$e_key])) . ','; } $csv .= "\n"; } ob_end_clean(); $fileName = $type.'-'.date('YmdHis').'('.$count.').csv'; header("Content-type:text/csv"); header("Content-Disposition:attachment;filename=".iconv("UTF-8", "gb2312",$fileName)); header('Cache-Control:must-revalidate,post-check=0,pre-check=0'); header('Expires:0'); header('Pragma:public'); ob_end_clean(); echo $csv; } /** * 生成並下載csv檔案 */ public function csv_export_f($keys , $expData , $fileName) { // export file $csv = ''; foreach ($keys as $key){ $csv .= '"'.iconv("UTF-8", "gb2312",$key).'",'; } $csv .= "\n"; foreach($expData as $expArr) { foreach ($expArr as $e_key=>$exp){ $csv .= iconv("UTF-8", "gbk",$this->escapeCSV($expArr[$e_key])) . ','; } $csv .= "\n"; } ob_end_clean(); $fileName .= '.csv'; header("Content-type:text/csv"); header("Content-Disposition:attachment;filename=".iconv("UTF-8", "gb2312",$fileName)); header('Cache-Control:must-revalidate,post-check=0,pre-check=0'); header('Expires:0'); header('Pragma:public'); ob_end_clean(); echo $csv; } function escapeCSV($str){ $str = str_replace(array(',','"',"\n\r"),array('','""',''),$str); if($str == ""){ $str = '""'; } return $str; } public function allData($rows) { foreach($rows as $row){ echo '<tr><td>'.implode('</td><td>',$row)."</td></tr>\r\n"; } ob_flush(); flush(); } public function oneData($row) { echo '<tr><td>'.implode('</td><td>',$row)."</td></tr>\r\n"; ob_flush(); flush(); } function end(){ echo '</table>'; ob_flush(); flush(); } /* * 多條資料flush一次 預設1000,有初始化物件決定 * */ public function multiData( $row ) { $this->rowCount++; echo '<tr><td>'.implode('</td><td>',$row)."</td></tr>\r\n"; if( $this->rowCount >= $this->rowFlushCount ) { ob_flush(); flush(); } } }

類包封裝完成後就可以寫業務程式碼,匯出的資料了

<?php
/*匯出1000000萬條資料例項*/


/*匯入類包*/
require('xlsTools.php');

/*例項化類包*/
$xlsTools = new xlsTools();


//定義列名和匯出名稱以及格式
$xlsTools->start([
    'title'=>['列名1','列名2'],   //列名
    'type'=>'xls',               //匯出的excel的型別
    'name'=>'匯出'                //匯出的excel的檔名
]);

/* 匯出100萬條(1000000條)示例 */
//這裡可以是我們資料庫查出來的資料,按照這種格式拼裝即可
for ($i=0; $i<1000000; $i++){
    $row = ['列值1'=>1,'列值2'=>'x'];

    //輸出資料,並重新整理緩衝區
    $xlsTools->oneData($row);
}

/*結束匯出*/
$xlsTools->end();

按自己的業務需求查出資料使用即可

注:雖然匯出的資料不會崩潰,但是過百萬的資料匯出時間過長,需要配置伺服器最大請求時間