PHP实现实时生成并下载超大数据量的EXCEL文件详解


Posted in PHP onOctober 23, 2017

前言

最近在工作中接到一个需求,通过选择的时间段导出对应的用户访问日志到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");在下载前告诉浏览器这个文件有多大了。不过不影响整体的效果这里的核心问题是解决大文件的实时生成和下载。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

PHP 相关文章推荐
十天学会php之第一天
Oct 09 PHP
Windows下利用Gvim写PHP产生中文乱码问题解决方法
Apr 20 PHP
php 删除一个数组中的某个值.兼容多维数组!
Feb 18 PHP
php时间戳转换的示例
Mar 31 PHP
php自定义错误处理用法实例
Mar 20 PHP
php实现对象克隆的方法
Jun 20 PHP
php获取指定(访客)IP所有信息(地址、邮政编码、国家、经纬度等)的方法
Jul 06 PHP
PHP模板引擎Smarty内建函数foreach,foreachelse用法分析
Apr 11 PHP
给大家分享几个常用的PHP函数
Jan 15 PHP
实现php删除链表中重复的结点
Sep 27 PHP
Laravel框架实现简单的学生信息管理平台案例
May 07 PHP
VSCode+PHPstudy配置PHP开发环境的步骤详解
Aug 20 PHP
Laravel学习教程之model validation的使用示例
Oct 23 #PHP
laravel实现批量更新多条记录的方法示例
Oct 22 #PHP
利用PHP获取汉字首字母并且分组排序详解
Oct 22 #PHP
Laravel 5.4因特殊字段太长导致migrations报错的解决
Oct 22 #PHP
PHP高效获取远程图片尺寸和大小的实现方法
Oct 20 #PHP
PHP静态延迟绑定和普通静态效率的对比
Oct 20 #PHP
php+ajax实现仿百度查询下拉内容功能示例
Oct 20 #PHP
You might like
php mysql索引问题
2008/06/07 PHP
php获得url参数中具有&amp;的值的方法
2014/03/05 PHP
yii2缓存Caching基本用法示例
2016/07/18 PHP
php实现简易计算器
2020/08/28 PHP
jquery+css+ul模拟列表菜单具体实现思路
2013/04/15 Javascript
浅析JS中document对象的一些重要属性
2014/03/06 Javascript
简单对比分析JavaScript中的apply,call与this的使用
2015/12/04 Javascript
悬浮广告方法日常收集整理
2016/03/18 Javascript
省市二级联动小案例讲解
2016/07/24 Javascript
js HTML5手机刮刮乐代码
2020/09/29 Javascript
js 数组详细操作方法及解析合集
2018/06/01 Javascript
微信小程序实现聊天对话(文本、图片)功能
2018/07/06 Javascript
JS封装的模仿qq右下角消息弹窗功能示例
2018/08/22 Javascript
AngularJS修改model值时,显示内容不变的实例
2018/09/13 Javascript
js实现数字从零慢慢增加到指定数字示例
2019/11/07 Javascript
JavaScript文档加载模式以及元素获取
2020/07/28 Javascript
[02:38]DOTA2 夜魇暗潮2020活动介绍官方视频
2020/11/04 DOTA
Python单例模式实例分析
2015/01/14 Python
Python编程入门的一些基本知识
2015/05/13 Python
python数据类型_字符串常用操作(详解)
2017/05/30 Python
Python的IDEL增加清屏功能实例
2017/06/19 Python
Python 等分切分数据及规则命名的实例代码
2019/08/16 Python
python socket通信编程实现文件上传代码实例
2019/12/14 Python
python openCV自制绘画板
2020/10/27 Python
python 如何设置守护进程
2020/10/29 Python
HTML5 Web Workers之网站也能多线程的实现
2013/04/24 HTML / CSS
英国在线购买轮胎、预订汽车、汽车维修和装配网站:Protyre
2020/04/12 全球购物
软件测试题目
2013/02/27 面试题
教师演讲稿范文
2014/01/08 职场文书
幼儿园托班开学寄语
2014/01/18 职场文书
超市开业庆典策划方案
2014/05/14 职场文书
大学英语专业求职信
2014/06/21 职场文书
收费员岗位职责
2015/02/14 职场文书
react中props 的使用及进行限制的方法
2021/04/28 Javascript
详解thinkphp的Auth类认证
2021/05/28 PHP
Redis高可用集群redis-cluster详解
2022/03/20 Redis