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 相关文章推荐
excellent!――ASCII Art(由目标图象生成ascii)
Feb 20 PHP
php中的实现trim函数代码
Mar 19 PHP
如何提高MYSQL数据库的查询统计速度 select 索引应用
Apr 11 PHP
php验证手机号码(支持归属地查询及编码为UTF8)
Feb 01 PHP
解析PHP中如何将数组变量写入文件
Jun 06 PHP
PHP5.5和之前的版本empty函数的不同之处
Jun 13 PHP
ThinkPHP中Session用法详解
Nov 29 PHP
PHP使用适合阅读的格式显示文件大小的方法
Mar 05 PHP
php实现的验证码文件类实例
Jun 18 PHP
Symfony2学习笔记之插件格式分析
Mar 17 PHP
PHP常用日期加减计算方法实例小结
Jul 31 PHP
PHP按一定比例压缩图片的方法
Oct 12 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文本操作类
2006/11/25 PHP
php中++i 与 i++ 的区别
2012/08/08 PHP
php 表单提交大量数据发生丢失的解决方法
2014/03/03 PHP
ThinkPHP分页类使用详解
2014/03/05 PHP
PHP面向对象编程之深入理解方法重载与方法覆盖(多态)
2015/12/24 PHP
Yii框架实现对数据库的CURD操作示例
2019/09/03 PHP
使用Jquery搭建最佳用户体验的登录页面之记住密码自动登录功能(含后台代码)
2011/07/10 Javascript
兼容IE和FF的图片上传前预览js代码
2013/05/28 Javascript
仿百度的关键词匹配搜索示例
2013/09/25 Javascript
jquery实现带二级菜单的导航示例
2014/04/28 Javascript
深入分析Javascript跨域问题
2015/04/17 Javascript
详解jQuery中的元素的属性和相关操作
2015/08/14 Javascript
JavaScript中var关键字的使用详解
2015/08/14 Javascript
javascript实现一个简单的弹出窗
2016/02/22 Javascript
BootStrap创建响应式导航条实例代码
2016/05/31 Javascript
AngularJS基础 ng-selected 指令简单示例
2016/08/03 Javascript
利用jqprint插件打印页面内容的实现方法
2018/01/09 Javascript
详解vue中axios的封装
2018/07/18 Javascript
layer提示框添加多个按钮选择的实例
2019/09/12 Javascript
浅谈javascript如何获取文件后缀名
2020/08/07 Javascript
利用python获得时间的实例说明
2013/03/25 Python
从零学python系列之数据处理编程实例(一)
2014/05/22 Python
python实现文本进度条 程序进度条 加载进度条 单行刷新功能
2019/07/03 Python
Django forms表单 select下拉框的传值实例
2019/07/19 Python
解决django-xadmin列表页filter关联对象搜索问题
2019/11/15 Python
如何用OpenCV -python3实现视频物体追踪
2019/12/04 Python
如何在 Matplotlib 中更改绘图背景的实现
2020/11/26 Python
阿迪达斯丹麦官网:adidas丹麦
2016/10/01 全球购物
Ajax的工作原理
2015/12/04 面试题
教师自荐书
2013/10/08 职场文书
银行柜员求职自荐书
2014/06/18 职场文书
禁毒宣传标语
2014/06/19 职场文书
铁人纪念馆观后感
2015/06/16 职场文书
CSS 文字装饰 text-decoration & text-emphasis 详解
2021/04/06 HTML / CSS
MySQL派生表联表查询实战过程
2022/03/20 MySQL
《英雄联盟》2022日蚀、月蚀皮肤演示 黑潮亚索曝光
2022/04/13 其他游戏