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 网页过期时间的控制代码
Jun 29 PHP
收集的二十一个实用便利的PHP函数代码
Apr 22 PHP
php中批量删除Mysql中相同前缀的数据表的代码
Jul 01 PHP
PHP 中关于ord($str)&amp;gt;0x80的详细说明
Sep 23 PHP
PHP上传图片进行等比缩放可增加水印功能
Jan 13 PHP
ThinkPHP查询中的魔术方法简述
Jun 25 PHP
php中的字符编码转换函数用法示例
Oct 20 PHP
PHP微信支付实例解析
Jul 22 PHP
Yii2 如何在modules中添加验证码的方法
Jun 19 PHP
PHP基于redis计数器类定义与用法示例
Feb 08 PHP
PHP单例模式实例分析【防继承,防克隆操作】
May 22 PHP
laravel 解决多库下的DB::transaction()事务失效问题
Oct 21 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
PHP5 的对象赋值机制介绍
2011/08/02 PHP
PHP编程函数安全篇
2013/01/08 PHP
WIN8.1下搭建PHP5.6环境
2015/04/29 PHP
Centos6.5和Centos7 php环境搭建方法
2016/05/27 PHP
对php 判断http还是https,以及获得当前url的方法详解
2019/01/15 PHP
jqGrid日期格式的判断示例代码(开始日期与结束日期)
2013/11/08 Javascript
JavaScript调试技巧之console.log()详解
2014/03/19 Javascript
JS兼容浏览器的导出Excel(CSV)文件的方法
2014/05/03 Javascript
jquery实现触发时更新下拉列表内容的方法
2015/12/02 Javascript
javascript实现起伏的水波背景效果
2016/05/16 Javascript
微信+angularJS的SPA应用中用router进行页面跳转,jssdk校验失败问题解决
2016/09/09 Javascript
浅谈js for循环输出i为同一值的问题
2017/03/01 Javascript
Angular中的$watch、$watchGroup、$watchCollection
2017/06/25 Javascript
Angular 表单控件示例代码
2017/06/26 Javascript
详解使用nvm安装node.js
2017/07/18 Javascript
浅析webpack 如何优雅的使用tree-shaking(摇树优化)
2017/08/16 Javascript
vue基于两个计算属性实现选中和全选功能示例
2019/02/08 Javascript
js定义类的方法示例【ES5与ES6】
2019/07/30 Javascript
基于vue-cli3和element实现登陆页面
2019/11/13 Javascript
js防抖函数和节流函数使用场景和实现区别示例分析
2020/04/11 Javascript
[02:04]2020年夜魇暗潮预告片
2020/10/30 DOTA
Python中的Classes和Metaclasses详解
2015/04/02 Python
Python的Flask框架及Nginx实现静态文件访问限制功能
2016/06/27 Python
Python操作使用MySQL数据库的实例代码
2017/05/25 Python
python3.6 +tkinter GUI编程 实现界面化的文本处理工具(推荐)
2017/12/20 Python
CentOS7.3编译安装Python3.6.2的方法
2018/01/22 Python
如何打包Python Web项目实现免安装一键启动的方法
2020/05/21 Python
pycharm开发一个简单界面和通用mvc模板(操作方法图解)
2020/05/27 Python
二年级小学生评语
2014/04/21 职场文书
中班上学期幼儿评语
2014/04/30 职场文书
电子信息专业应届生自荐信
2014/06/04 职场文书
入党积极分子学习优秀共产党员先进事迹思想汇报
2014/09/13 职场文书
同学毕业留言寄语
2015/02/27 职场文书
用Python远程登陆服务器的步骤
2021/04/16 Python
详解分布式系统中如何用python实现Paxos
2021/05/18 Python
一定要知道的 25 个 Vue 技巧
2021/11/02 Vue.js