国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 語言 > PHP > 正文

PHP實現(xiàn)實時生成并下載超大數(shù)據(jù)量的EXCEL文件詳解

2024-05-05 00:00:40
字體:
供稿:網(wǎng)友

前言

最近在工作中接到一個需求,通過選擇的時間段導(dǎo)出對應(yīng)的用戶訪問日志到excel中, 由于用戶量較大,經(jīng)常會有導(dǎo)出50萬加數(shù)據(jù)的情況。而常用的PHPexcel包需要把所有數(shù)據(jù)拿到后才能生成excel, 在面對生成超大數(shù)據(jù)量的excel文件時這顯然是會造成內(nèi)存溢出的,所以考慮使用讓PHP邊寫入輸出流邊讓瀏覽器下載的形式來完成需求。

我們通過如下的方式寫入PHP輸出流

php;">$fp = fopen('php://output', 'a');fputs($fp, 'strings');........fclose($fp)

php://output是一個可寫的輸出流,允許程序像操作文件一樣將輸出寫入到輸出流中,PHP會把輸出流中的內(nèi)容發(fā)送給web服務(wù)器并返回給發(fā)起請求的瀏覽器

另外由于excel數(shù)據(jù)是從數(shù)據(jù)庫里逐步讀出然后寫入輸出流的所以需要將PHP的執(zhí)行時間設(shè)長一點(默認(rèn)30秒)set_time_limit(0)不對PHP執(zhí)行時間做限制。

注:以下代碼只是闡明生成大數(shù)據(jù)量EXCEL的思路和步驟,并且在去掉項目業(yè)務(wù)代碼后程序有語法錯誤不能拿來直接運行,請根據(jù)自己的需求填充對應(yīng)的業(yè)務(wù)代碼!

 /**  * 文章訪問日志  * 下載的日志文件通常很大, 所以先設(shè)置csv相關(guān)的Header頭, 然后打開  * PHP output流, 漸進(jìn)式的往output流中寫入數(shù)據(jù), 寫到一定量后將系統(tǒng)緩沖沖刷到響應(yīng)中  * 避免緩沖溢出  */ public function articleAccessLog($timeStart, $timeEnd) {  set_time_limit(0);  $columns = [   '文章ID', '文章標(biāo)題', ......  ];  $csvFileName = '用戶日志' . $timeStart .'_'. $timeEnd . '.xlsx';  //設(shè)置好告訴瀏覽器要下載excel文件的headers  header('Content-Description: File Transfer');  header('Content-Type: application/vnd.ms-excel');  header('Content-Disposition: attachment; filename="'. $fileName .'"');  header('Expires: 0');  header('Cache-Control: must-revalidate');  header('Pragma: public');  $fp = fopen('php://output', 'a');//打開output流  mb_convert_variables('GBK', 'UTF-8', $columns);  fputcsv($fp, $columns);//將數(shù)據(jù)格式化為CSV格式并寫入到output流中  $accessNum = '1000000'//從數(shù)據(jù)庫獲取總量,假設(shè)是一百萬  $perSize = 1000;//每次查詢的條數(shù)  $pages = ceil($accessNum / $perSize);  $lastId = 0;  for($i = 1; $i <= $pages; $i++) {   $accessLog = $logService->getArticleAccessLog($timeStart, $timeEnd, $lastId, $perSize);   foreach($accessLog as $access) {    $rowData = [     ......//每一行的數(shù)據(jù)    ];    mb_convert_variables('GBK', 'UTF-8', $rowData);    fputcsv($fp, $rowData);    $lastId = $access->id;   }   unset($accessLog);//釋放變量的內(nèi)存   //刷新輸出緩沖到瀏覽器   ob_flush();   flush();//必須同時使用 ob_flush() 和flush() 函數(shù)來刷新輸出緩沖。  }  fclose($fp);  exit(); }

好了, 其實很簡單,就是用逐步寫入輸出流并發(fā)送到瀏覽器讓瀏覽器去逐步下載整個文件,由于是逐步寫入的無法獲取文件的總體size所以就沒辦法通過設(shè)置header("Content-Length: $size");在下載前告訴瀏覽器這個文件有多大了。不過不影響整體的效果這里的核心問題是解決大文件的實時生成和下載。

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,如果有疑問大家可以留言交流,謝謝大家對VeVb武林網(wǎng)的支持。


注:相關(guān)教程知識閱讀請移步到PHP教程頻道。
發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表

圖片精選

主站蜘蛛池模板: 崇州市| 长阳| 大同市| 晋宁县| 蕲春县| 巴彦淖尔市| 宜宾市| 德化县| 南木林县| 巍山| 蒙自县| 宜兴市| 舒城县| 苍梧县| 昌乐县| 阜新市| 南华县| 肃南| 巫山县| 贺兰县| 鹿泉市| 郓城县| 江北区| 文水县| 辛集市| 岗巴县| 龙江县| 太仆寺旗| 博爱县| 德保县| 曲靖市| 绥中县| 黎川县| 富宁县| 额尔古纳市| 武夷山市| 福泉市| 洛阳市| 白银市| 凤台县| 蚌埠市|