亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

PHP實(shí)時(shí)生成并下載超大數(shù)據(jù)量的EXCEL文件

Neilyo / 1176人閱讀

摘要:而常用的包需要把所有數(shù)據(jù)拿到后才能生成,在面對(duì)生成超大數(shù)據(jù)量的文件時(shí)這顯然是會(huì)造成內(nèi)存溢出的,所以考慮使用讓邊寫入輸出流邊讓瀏覽器下載的形式來(lái)完成需求。

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

我們通過(guò)如下的方式寫入PHP輸出流

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

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

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

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

    /**
     * 文章訪問(wèn)日志
     * 下載的日志文件通常很大, 所以先設(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"http://從數(shù)據(jù)庫(kù)獲取總量,假設(shè)是一百萬(wàn)
        $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();//必須同時(shí)使用 ob_flush() 和flush() 函數(shù)來(lái)刷新輸出緩沖。
        }
        fclose($fp);
        exit();
    }

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


更新: 說(shuō)一下我數(shù)據(jù)庫(kù)查詢這里的思路,因?yàn)橹鸩綄懭隕XCEL的數(shù)據(jù)實(shí)際上來(lái)自Mysql的分頁(yè)查詢,大家知道其語(yǔ)法是LIMIT offset, num 不過(guò)隨著offset越來(lái)越大Mysql在每次分頁(yè)查詢時(shí)需要跳過(guò)的行數(shù)就越多,這會(huì)嚴(yán)重影響Mysql查詢的效率(包括MongoDB這樣的NoSQL也是不建議skip掉多條來(lái)取結(jié)果集),所以我采用LastId的方式來(lái)做分頁(yè)查詢。 類似下面的語(yǔ)句:

SELECT columns FROM `table_name` 
WHERE `created_at` >= "time range start" 
AND `created_at` <= "time range end" 
AND  `id` < LastId 
ORDER BY `id` DESC 
LIMIT num 

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/30697.html

相關(guān)文章

  • 【SpringMvc】后臺(tái)系統(tǒng)超大報(bào)表下載超時(shí)的處理

    摘要:四層負(fù)載均衡不會(huì)引起超時(shí)。動(dòng)態(tài)修改包的目標(biāo)地址,并轉(zhuǎn)發(fā)數(shù)據(jù)包使其到達(dá)不同的機(jī)器上來(lái)實(shí)現(xiàn)負(fù)載均衡的目的,因此節(jié)點(diǎn)不會(huì)引起超時(shí)。七層負(fù)載均衡等待上游響應(yīng)超時(shí)。例如使用多線程并發(fā)減少遠(yuǎn)程查詢的總體時(shí)間如需數(shù)據(jù)有序,可以使用方案。 B端業(yè)務(wù)經(jīng)常要提供下載報(bào)表的功能,一般的方法是先查詢出所有數(shù)據(jù),然后在內(nèi)存中組裝成報(bào)表(如XLS/XLSX格式)后統(tǒng)一輸出。但是如果生成報(bào)表需要查詢的數(shù)據(jù)量很大,遠(yuǎn)...

    kohoh_ 評(píng)論0 收藏0
  • PHP讀取超大excel文件數(shù)據(jù)的方案

    摘要:場(chǎng)景和痛點(diǎn)說(shuō)明今天因?yàn)橐粋€(gè)老同學(xué)找我,說(shuō)自己公司的物流業(yè)務(wù)都是現(xiàn)在用處理,按月因?yàn)閿?shù)據(jù)量大,一個(gè)差不多有百萬(wàn)數(shù)據(jù),文件有接近,打開和搜索就相當(dāng)?shù)穆?lián)想到場(chǎng)景要導(dǎo)入數(shù)據(jù),可能數(shù)據(jù)量很大,這里利用常用的一些方法比如會(huì)常有時(shí)間和內(nèi)存限制問(wèn)題下面我 場(chǎng)景和痛點(diǎn) 說(shuō)明 今天因?yàn)橐粋€(gè)老同學(xué)找我,說(shuō)自己公司的物流業(yè)務(wù)都是現(xiàn)在用excel處理,按月因?yàn)閿?shù)據(jù)量大,一個(gè)excel差不多有百萬(wàn)數(shù)據(jù),文件有接...

    dkzwm 評(píng)論0 收藏0
  • php 導(dǎo)出 excel

    關(guān)于 PHP 導(dǎo)出 excel csv 常用的有 PHPexcel ,本文整理了一些其他方案。 高性能 Excel 擴(kuò)展 sudo apt-get install -y zlib1g-dev git clone https://github.com/jmcnamara/libxlsxwriter.git cd libxlsxwriter make && sudo make install // ...

    付永剛 評(píng)論0 收藏0
  • PHP導(dǎo)出超大的CSV格式的Excel表方案

    摘要:場(chǎng)景和痛點(diǎn)說(shuō)明我們工作場(chǎng)景都常會(huì)導(dǎo)出相關(guān)的數(shù)據(jù),有時(shí)候需要大量的數(shù)據(jù),,都有可能我們現(xiàn)有方案都是直接利用等類庫(kù)來(lái)操作,的加載或是寫入一次導(dǎo)出會(huì)遇到超時(shí)內(nèi)存和時(shí)間限制問(wèn)題,就算我們依舊不是最好的方案下面我們利用輸出,把數(shù)據(jù)依次輸出清空再輸出的 場(chǎng)景和痛點(diǎn) 說(shuō)明 我們工作場(chǎng)景都常會(huì)導(dǎo)出相關(guān)的excel數(shù)據(jù),有時(shí)候需要大量的數(shù)據(jù),10W,100W都有可能我們現(xiàn)有方案都是直接利用phpexce...

    yedf 評(píng)論0 收藏0
  • PHPPHPExcelexcel常用操作小結(jié)

    摘要:使用好久了,好像今天才想起來(lái)要記一篇博客呢。之前一直用的框架,后來(lái)做接口的時(shí)候打算換成不料機(jī)緣巧合之下又結(jié)識(shí)了,于是乎決然的站到了的大營(yíng)之下。今天小記一下這個(gè)類庫(kù)的常用操作。首先貼上地址,直接去下載最新版好了。 PHP使用好久了,好像今天才想起來(lái)要記一篇博客呢。之前一直用的 ci 框架,后來(lái)做接口的時(shí)候打算換成 tp5, 不料機(jī)緣巧合之下又結(jié)識(shí)了 node,于是乎決然的站到了 js 的...

    suosuopuo 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<