PHP实现实时⽣成并下载超⼤数据量的EXCEL⽂件详解前⾔
最近在⼯作中接到⼀个需求,通过选择的时间段导出对应的⽤户访问⽇志到excel中,由于⽤户量较⼤,经常会有导出50万加数据的情况。⽽常⽤的PHPexcel包需要把所有数据拿到后才能⽣成excel,在⾯对⽣成超⼤数据量的excel⽂件时这显然是会造成内存溢出的,所以考虑使⽤让PHP边写⼊输出流边让浏览器下载的形式来完成需求。
我们通过如下的⽅式写⼊PHP输出流
$fp = fopen('php://output', 'a');
fputs($fp, 'strings');
php手机版下载
....
....
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");在下载前告诉浏览器这个⽂件有多⼤了。不过不影响整体的效果这⾥的核⼼问题是解决⼤⽂件的实时⽣成和下载。
总结
以上就是这篇⽂章的全部内容了,希望本⽂的内容对⼤家的学习或者⼯作具有⼀定的参考学习价值,如果有疑问⼤家可以留⾔交流,谢谢⼤家对的⽀持。