Thinkphp5 分批批量导出百万条数据记录的Code,不用PHPEXCEL哦!

2018年03月24日 6,363 次阅读 38 条评论 204 人点赞

通过phpexcel导出上万条数据,会延迟、内存溢出、程序报错,各种问题出现...届时作者放弃了phpexcel,导出小数据量还是很可行的。下面通过分批导出csv,并压缩至zip中提供下载...废话不说上代码...部分代码参考网上的哦~~~

问题:通过phpexcel导出上万条数据,会延迟、内存溢出、程序报错,各种问题出现...届时作者放弃了phpexcel,导出小数据量还是很可行的。下面通过分批导出csv,并压缩至zip中提供下载...废话不说上代码...部分代码参考网上的哦~~~ fans_list 方法为作者自己封装的方法,可根据自己的情况来写,其实就是根据参数返回数据集而已。

/**
 * csv 批量导出
 * @param $mpid
 * @throws \think\db\exception\DataNotFoundException
 * @throws \think\db\exception\ModelNotFoundException
 * @throws \think\exception\DbException
 */
public function export($mpid)
{
    $wechat_mp_model = new WechatMp();

    $limit = 50000;//每次只从数据库取50000条以防变量缓存太大
    // buffer计数器
    $cnt = 0;

    $where['mpid'] = $mpid;
    $mpName = $wechat_mp_model->getCustomField($where, 'mpname');
    $start_time = $this->request->param('start_time', '');
    $end_time = $this->request->param('end_time', '');
    $args['start_time'] = $start_time;
    $args['end_time'] = $end_time;
    $xlsTitle = ['关注时间', '微信Openid', '微信昵称', '微信头像', '性别'];

    set_time_limit(0);

    $sqlCount = $this->get_fans_list($mpid, 0, $limit, $args, true);
    $fileName = iconv('utf-8', 'gb2312', $mpName);//文件名称
    $fileName = $fileName . date('_YmdHis');// 文件名称可根据自己情况设定
    // 输出Excel文件头,可把user.csv换成你要的文件名
    header('Content-Type: application/vnd.ms-excel;charset=utf-8');
    header('Content-Disposition: attachment;filename="' . $fileName . '"');
    header('Cache-Control: max-age=0');

    $fileNameArr = array();
    // 逐行取出数据,不浪费内存
    for ($i = 0; $i < ceil($sqlCount / $limit); $i++) { 

        $fp = fopen($fileName . '_' . $i . '.csv', 'w'); //生成临时文件 
        // chmod('attack_ip_info_' . $i . '.csv',777);//修改可执行权限 
        $fileNameArr[] = $fileName . '_' . $i . '.csv'; // 将数据通过fputcsv写到文件句柄 
        fputcsv($fp, $xlsTitle); 
        $start = $i * $limit; 
        $dataArr = $this->get_fans_list($mpid, $start, $limit, $args);
        foreach ($dataArr as $a) {
            $cnt++;
            if ($limit == $cnt) {
                //刷新一下输出buffer,防止由于数据过多造成问题
                ob_flush();
                flush();
                $cnt = 0;
            }
            fputcsv($fp, $a);
        }
        fclose($fp);  //每生成一个文件关闭
    }
    //进行多个文件压缩
    $zip = new \ZipArchive();
    $filename = $fileName . ".zip";
    $zip->open($filename, $zip::CREATE);   //打开压缩包
    foreach ($fileNameArr as $file) {
        $zip->addFile($file, basename($file));   //向压缩包中添加文件
    }
    $zip->close();  //关闭压缩包
    foreach ($fileNameArr as $file) {
        unlink($file); //删除csv临时文件
    }
    $this->insertLog($this->admin_id, '', '导出公众号粉丝');
    //输出压缩文件提供下载
    header("Cache-Control: max-age=0");
    header("Content-Description: File Transfer");
    header('Content-disposition: attachment; filename=' . basename($filename)); // 文件名
    header("Content-Type: application/zip"); // zip格式的
    header("Content-Transfer-Encoding: binary"); //
    header('Content-Length: ' . filesize($filename)); //
    @readfile($filename);//输出文件;
    unlink($filename); //删除压缩包临时文件
}
目前本机没有百万数据,也就30万条左右,导出没有任何问题,而且效率杠杠的。大家在使用过程中有更好的建议,欢迎留言!!  

讲梦想、讲奋斗可以,前提是钱要给够。

文章评论(38

  • PHP啊Lv 1

    为什么 生成的临时文件CSV 有数据 打包压缩 就0kb 啊

    #112019-11-10 10:35
    • 阳阳博主

      @PHP啊检查代码,你有多少数据啊

      2019-11-11 08:54
  • 洋洋Lv 1

    502错误了了

    #102019-07-17 20:35
    • 阳阳博主

      @洋洋什么502错误了?

      2019-07-18 09:07
    • 洋洋Lv 1

      @阳阳服务器....

      2019-07-18 09:08
    • 阳阳博主

      @洋洋是我的博客502 还是说你的服务器502 。。。

      2019-07-18 09:08
    • 洋洋Lv 1

      @阳阳我的服务器

      2019-07-18 09:10
    • 阳阳博主

      @洋洋你多少数据量,我提供的这个方法绝对是没有问题的。仔细排查代码部分。

      2019-07-18 09:11
  • yudiecaoLv 1

    一个cvs文件,可以进行压缩下载,当cvs文件大于等于2个时,就会报错 报: Cannot modify header information - headers already sent 实在找不到解决办法了

    #92019-07-10 16:13
  • yudiecaoLv 1

    报错: Cannot modify header information - headers already sent 有什么解决办法吗

    #82019-07-10 16:12
    • 阳阳博主

      @yudiecao打开缓冲区试试

      2019-07-10 16:13
    • yudiecaoLv 1

      @阳阳是说 output_buffering = On吗?已经开启了

      2019-07-10 16:14
    • 阳阳博主

      @yudiecaoob_start 打开缓冲区, header函数前执行这个

      2019-07-10 16:15
    • yudiecaoLv 1

      @阳阳也已经添加了

      2019-07-10 16:24
    • 阳阳博主

      @yudiecao这个报错很常见,百度或google一下。

      2019-07-10 16:24
    • yudiecaoLv 1

      @阳阳好吧,基本百度的方法都试了,我自己研究吧

      2019-07-10 16:33
  • 小小酥Lv 1

    大佬能给我发一份么

    #72019-06-10 13:45
    • 阳阳博主

      @小小酥代码不是已经帖在文章里了麽,你还需要那部分代码呢!

      2019-06-10 14:37
  • 实习Lv 1

    博主能把这个方法分享出来参考一下吗 get_fans_list

    #62019-04-27 11:42
    • 阳阳博主

      @实习留下你的QQ邮箱,待会发你邮箱!

      2019-04-27 11:44
    • 实习Lv 1

      @阳阳好的,谢谢

      2019-04-27 11:45
    • 求 get_fans_list方法Lv 1

      @实习21573579@qq.com 求 get_fans_list方法

      2019-05-08 15:50
    • 求 get_fans_list方法Lv 1

      @阳阳博主跪求 get_fans_list方法 21573579@qq.com

      2019-05-08 15:51
    • 阳阳博主

      @求 get_fans_list方法这个方法没啥可参考的,就是获取数据的一个方法,已经发送你的邮箱

      2019-05-08 15:53
    • 求 get_fans_list方法Lv 1

      @阳阳好的 已经收到 非常谢谢

      2019-05-08 15:55
    • 实习Lv 1

      @求 get_fans_list方法然而并没有发

      2019-05-08 16:08
    • 求 get_fans_list方法Lv 1

      @实习那就是阳阳发的

      2019-05-08 16:23
    • 阳阳博主

      @实习已经给你邮箱发过的~~~呵呵~~当时你没有回复邮箱,是根据后台你留言留下的邮箱发送的!

      2019-05-08 22:17
    • 求get_fans_list方法Lv 1

      @阳阳764363215@qq.com 求get_fans_list方法 谢谢

      2019-05-15 11:46
    • 阳阳博主

      @求get_fans_list方法评论区截图的就是这个方法,这个方法就是返回数据集,没啥可参考的。

      2019-05-15 12:56
    • fdsfdfdsfdsLv 1

      @实习六六六佛挡杀佛地方

      2019-05-23 19:41
  • php小白Lv 1

    thinkphp 3.2.3 可以用吗

    #52019-03-27 10:34
    • 阳阳博主

      @php小白代码作为参考,tp3.2也是可以用的。

      2019-03-27 10:36
  • php小白Lv 1

    thinkphp 3.2.3 可以用吗

    #42019-03-27 10:34
  • phpLv 1

    导入有教程吗

    #32018-11-20 18:13
    • 阳阳博主

      @php导入教程,网上太多了,可以参考以下。

      2018-11-21 07:56
  • 阳阳博主

    昨日有人问我,为什么采用了代码无法正常导出,经过排查是因为他没有安装zlib和zip 的扩展,所以如果大家有遇到代码排查正常仍无法导出,请检查是否正确安装php扩展

    #22018-04-21 10:02
  • 接收回复邮件通知
    非注册会员初次评论需要审核,审核时间(09:00-18:00),请耐心等待...