PHP实时生成并下载超大数据量的EXCEL文件-php教程

资源魔 17 0
比来接到一个需要,经过抉择的工夫段导出对应的用户拜访日记到excel中, 因为用户量较年夜,常常会有导出50万加数据的状况。

而罕用的PHPexcel包需求把一切数据拿到后能力天生excel, 正在面临天生超年夜数据量的excel文件时这显然是会造成内存溢出的,以是思考应用让PHP边写入输入流边让阅读器下载的方式来实现需要。

咱们经过以下的形式写入PHP输入流

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

php://output是一个可写的输入流,容许顺序像操作文件同样将输入写入到输入流中,PHP会把输入流中的内容发送给web效劳器并前往给发动申请的阅读器

另外因为excel数据是从数据库里逐渐读出而后写入输入流的以是需求将PHP的执行工夫设长一点(默许30秒)set_time_limit(0)不合错误PHP执行工夫做限度。

注:

如下代码只是说明天生年夜数据量EXCEL的思绪以及步骤,而且正在去掉名目营业代码后顺序有语法谬误不克不及拿来间接运转,请依据本人的需要填充对应的营业代码!

/**
     * 文章拜访日记
     * 下载的日记文件通常很年夜, 以是先设置csv相干的Header头, 而后关上
     * PHP output流, 渐进式的往output流中写入数据, 写到肯定量后将零碎缓冲冲洗到呼应中
     * 防止缓冲溢出
     */
    public function articleAccessLog($timeStart, $timeEnd)
    {
        set_time_limit(0);
        $columns = [
            '文章ID', '文章题目', ......
        ];
        $csvFileName = '用户日记' . $timeStart .'_'. $timeEnd . '.xlsx';
        //设置好通知阅读器要下载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);//将数据格局化为CSV格局并写入到output流中
        $accessNum = '1000000'//从数据库猎取总量,假定是一百万
        $perSize = 1000;//每一次查问的条数
        $pages   = ceil($accessNum / $perSize);
        $lastId  = 0;
        for($i = 1; $i <= $pages; $i++) {
            $accessLog = $logService->getArticleAccessLog($timeStart, $timeEnd, $lastId, $perSize);
            foreach($accessLog as $access) {
                $rowData = [
                    ......//每一一行的数据
                ];
                mb_convert_variables('GBK', 'UTF-8', $rowData);
                fputcsv($fp, $rowData);
                $lastId = $access->id;
            }
            unset($accessLog);//开释变量的内存
            //刷新输入缓冲到阅读器
            ob_flush();
            flush();//必需同时应用 ob_flush() 以及flush() 函数来刷新输入缓冲。
        }
        fclose($fp);
        exit();
    }

好了, 其实很简略,就是用逐渐写入输入流并发送到阅读器让阅读器去逐渐下载整个文件,因为是逐渐写入的无奈猎取文件的总体size以是就没方法经过设置header("Content-Length: $size");正在下载前通知阅读器这个文件有多年夜了。不外没有影响全体的成果这里的外围成绩是处理年夜文件的及时天生以及下载。

更新: 说一下我数据库查问这里的思绪,由于逐渐写入EXCEL的数据实际下去自Mysql的分页查问,各人晓得其语法是LIMIT offset, num 不外跟着offset愈来愈年夜Mysql正在每一次分页查问时需求跳过的行数就越多,这会重大影响Mysql查问的效率(包罗MongoDB这样的NoSQL也是没有倡议skip掉多条来取后果集),以是我采纳LastId的形式来做分页查问。

相似上面的语句:

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

以上就是PHP及时天生并下载超年夜数据量的EXCEL文件的具体内容,更多请存眷资源魔其它相干文章!

标签: php php开发教程 php开发资料 php开发自学 excel

抱歉,评论功能暂时关闭!