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脚本的10个技巧(7)
Oct 09 PHP
基于mysql的bbs设计(一)
Oct 09 PHP
php smarty模版引擎中的缓存应用
Dec 11 PHP
基于Windows下Apache PHP5.3.1安装教程
Jan 08 PHP
PHP开发负载均衡指南
Jul 17 PHP
php中去除所有js,html,css代码
Oct 12 PHP
比较discuz和ecshop的截取字符串函数php版
Sep 03 PHP
PHP时间戳 strtotime()使用方法和技巧
Oct 29 PHP
PHP中is_file不能替代file_exists的理由
Mar 04 PHP
PHP+Mysql+Ajax+JS实现省市区三级联动
May 23 PHP
PHP使用GD库输出汉字的方法【测试可用】
Nov 10 PHP
thinkphp jquery实现图片上传和预览效果
Jul 22 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
单一index.php实现PHP任意层级文件夹遍历(Zjmainstay原创)
2012/07/31 PHP
php中ltrim()、rtrim()与trim()删除字符空格实例
2014/11/25 PHP
php实现根据IP地址获取其所在省市的方法
2015/04/30 PHP
laravel-admin 实现在指定的相册下添加照片
2019/10/21 PHP
js实现双向链表互联网机顶盒实战应用实现
2011/10/28 Javascript
基于MVC3方式实现下拉列表联动(JQuery)
2013/09/02 Javascript
iframe窗口高度自适应的又一个巧妙实现思路
2014/04/04 Javascript
js实现文章文字大小字号功能完整实例
2014/11/01 Javascript
jquery实现用户打分评分特效
2015/05/28 Javascript
jQuery实现鼠标滑过图片移动特效
2016/12/08 Javascript
Vue写一个简单的倒计时按钮功能
2018/04/20 Javascript
小程序视频或音频自定义可拖拽进度条的示例代码
2018/09/30 Javascript
基于JavaScript实现单例模式
2019/10/30 Javascript
jquery实现简单每周轮换的日历
2020/09/10 jQuery
Python实现mysql数据库更新表数据接口的功能
2017/11/19 Python
python之virtualenv的简单使用方法(必看篇)
2017/11/25 Python
使用anaconda的pip安装第三方python包的操作步骤
2018/06/11 Python
python实现五子棋人机对战游戏
2020/03/25 Python
Python实现Mysql数据统计及numpy统计函数
2019/07/15 Python
PyTorch中Tensor的拼接与拆分的实现
2019/08/18 Python
python实现的多任务版udp聊天器功能案例
2019/11/13 Python
python 定义类时,实现内部方法的互相调用
2019/12/25 Python
Python3实现mysql连接和数据框的形成(实例代码)
2020/01/17 Python
keras CNN卷积核可视化,热度图教程
2020/06/22 Python
HTML5 实战PHP之Web页面表单设计
2011/10/09 HTML / CSS
html5 拖拽及用 js 实现拖拽功能的示例代码
2020/10/23 HTML / CSS
美国受信赖的教育产品供应商:Nest Learning
2018/06/14 全球购物
英国可持续奢侈品包包品牌:Elvis & Kresse
2018/08/05 全球购物
美国环保妈妈、儿童和婴儿用品购物网站:The Tot
2019/11/24 全球购物
总经理工作职责范文
2014/03/14 职场文书
幼儿园毕业典礼主持词
2014/03/21 职场文书
综治宣传月活动总结
2014/04/28 职场文书
演讲比赛的活动方案
2014/08/28 职场文书
小学班级特色活动方案
2014/08/31 职场文书
力克胡哲观后感
2015/06/10 职场文书
Python中requests做接口测试的方法
2021/05/30 Python