Laravel5使用box/spout扩展,大文件导出CSV文件

一、背景

早期开发的系统,使用laravel框架,版本V5.4,项目经理导出 3 年的数据,由于数据量较大,浏览器卡死。一次性无法导出,某位程序员告知按月去导出,之后在拼凑,这。。搁谁受的了,我担心投诉,加个班优化下。

二、优化方案

  1. 导出数据的Sql,对应创建索引,提高查询速度
  2. 查询结果集使用 chunk() 方法拆分较小集合
  3. 使用box/spout扩展进行导出

三、box/spout扩展安装

由于服务器 PHP 的版本比较老,5.6,box/spout 版本只能安装 v2.7.3,安装流程:

3.1 安装

composer require box/spout:v2.7.3

3.2 使用导出功能

3.2.1 控制器中引入使用到的方法:

use Box\Spout\Common\Type;
use Box\Spout\Writer\WriterFactory;

3.2.2 主要代码示例:

// 实例化类,传递参数:Type::CSV 代表导出 csv 文件,支持 3 种格式
$writer = WriterFactory::create(Type::CSV);

// 浏览器下载方式
// 注意:这里的openToBrowser方法,扩展包源码只传递 1 个 参数,有修改源码,参考四。。
$filename = '文件名称.csv';
$aHeader = [
   'Content-Description: File Transfer',
   'Content-Disposition: attachment; filename=' . $filename,
   'Expires: 0',
   'Cache-Control: must-revalidate',
   'Pragma: public',
];
$writer->openToBrowser($filename, $aHeader);

// 支持文件存储
// 代码:$writer->openToFile("存储路径"); 

// addRow,添加单行 - 表头
$title = ['姓名', '年龄'];
$writer->addRow($title);

// addRow,添加单行 - 示例内容
$content = ['张大胆', 18];
$writer->addRow($content);

// [重要],添加多行内容,使用addRows。查询数据库之后的代码循环拼接内容,示例:
$aDates = [];
$aDates[] = [
		['李胆大', 20],
		['王老五', 25],
		['钱老三', 33],
];
// 假设 - 循环数据库查询结果集,拼多行内容。
foreach ($dbData as $data) 
	$aDatas[] = $data;
}
 // 添加多行
$writer->addRows($aDatas);
// 导出完毕后,关闭Writer对象:
$writer->close();

四、遇到的问题及修改源码包

本地windows环境导出正常,正式 centos 环境导出没有文件名,只有一个csv后缀文件。
怀疑是header的问题,修改源代码,自定义传递 header

修改源码位置:
vendor\box\spout\src\Spout\Writer\WriterInterface接口,30行,增加了 , $headers = []参数

public function openToBrowser($outputFileName, $headers = []);

vendor\box\spout\src\Spout\Writer\AbstractWriter类,134行,增加了 , $headers = []参数

public function openToBrowser($outputFileName, $headers = [])
    {
        $this->outputFilePath = $this->globalFunctionsHelper->basename($outputFileName);

        $this->filePointer = $this->globalFunctionsHelper->fopen('php://output', 'w');
        $this->throwIfFilePointerIsNotAvailable();

        // Clear any previous output (otherwise the generated file will be corrupted)
        // @see https://github.com/box/spout/issues/241
        $this->globalFunctionsHelper->ob_end_clean();

        // Set headers
        $this->globalFunctionsHelper->header('Content-Type: ' . static::$headerContentType);

        /*
         * When forcing the download of a file over SSL,IE8 and lower browsers fail
         * if the Cache-Control and Pragma headers are not set.
         *
         * @see http://support.microsoft.com/KB/323308
         * @see https://github.com/liuggio/ExcelBundle/issues/45
         */

        /*
         * 核心修改代码位置
         */
        foreach ($headers as $header){
            $this->globalFunctionsHelper->header($header);
        }

        $this->openWriter();
        $this->isWriterOpened = true;

        return $this;
    }

五、结果

筛选跨年数据一次性导出,皆大欢喜。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值