最近在工作中接到一个需求,通过选择的时间段导出对应的用户访问日志到csv中, 由于用户量较大,经常会有导出1000万加数据的情况。而常用的PHP excel包需要把所有数据拿到后才能生成excel, 在面对生成超大数据量的excel文件时这显然是会造成内存溢出的,由于excel在导出大文件的时候,尤其是特大文件,会有内存溢出问题和本身支持的原因。所以考虑使用让PHP边写入输出流边让浏览器下载的形式来完成需求,导出到csv文件中:
下面直接上代码吧:
set_time_limit ( 0 );
$fileName = "游戏用户日志细表";
ini_set('memory_limit', '1024M'); //设置程序运行的内存
ini_set('max_execution_time', 0); //设置程序的执行时间,0为无上限
ob_end_clean(); //清除内存
ob_start();
header("Content-Type: text/csv");
header("Content-Disposition:filename=" . $fileName . '.csv');
$fp = fopen('php://output', 'w');
fwrite($fp, chr(0xEF) . chr(0xBB) . chr(0xBF));
$headArr =[
'项目','类型','游戏券', '名称', '道具', '总金额', '申请人', '申请日期', '道具下发', '道具状态'
];
fputcsv($fp, $headArr);
//for($i=1;$i<=100000000;$i++){
$page = 1;
$limit = 100;
while(true) {
$listData = $data = [];
if($page < 1 || !$page) $page = 1;
$offset = ($page - 1) * $limit;
$data = $list->offset($offset)->limit($limit)->all();
if(!$data) break;
$voucherService = \Yii::$container->get(voucherService::class);
foreach($data as $item) {
$listData = [
'voucher_name' => $item['voucher_name'],
'type' => $item['type'],
'code' => $item['code'],
'title' => $item['title'],
'prop' => $item['prop'],
'amount' => $item['amount'],
'pay_amount' => $this->formatValue($item['pay_amount']),
'starting_time' => date("Y-m-d",strtotime($item['starting_time'])),
'payed_on' => $item['payed_on'],
'status' => voucherGameAR::STATUS_NAME[$item['status']],
];
fputcsv($fp, $listData);
}
ob_flush();//清除内存
flush();
$page++;
}
//}
ob_flush();
flush();
ob_end_clean();
exit();
实际场景中可以到3000万的数据,php不会超时,内存不会溢出