这时就须要循环批量写入excle导出。
过程中可能碰着的问题:
1.超时:Maximum execution time of 30 seconds exceeded
办理:在文件开头加上 set_time_limit(0);即php实行韶光不受限定。
2.内存溢出:Allowed memory size of 134217728 bytes exhausted (tried to allocate 20480 bytes)
办理:
2.1 可在ini文件设置;设置memory_limit,将内存设置加大,
2.2 在实行代码前加上 ini_set(\公众memory_limit\公众, \公众1024M\"大众);
2.3 每次读取的数据量减少,增加循环的次数;
3.导出的excle数字过长展示成科学计数
办理:
3.1 在要写入的数字数据,后面加个 “\t”;
3.2 或是数字转换为字符串格式
上代码(天生excle链接导出数据):
public function downBigExcle()
{
set_time_limit(0);
#自定义导出地址+文件名
$pathName = time().'.csv';
#打算要导出总数据条数
$totalNums = Db::table('t_excle')->count('id');
#设置表头标题
$headerTitleArr = ['xx','xxx'];
#CSV的Excel支持GBK编码,一定要转换,否则乱码
foreach ($headerTitleArr as $i => $v) {
$headerTitleArr[$i] = iconv('utf-8', 'gbk', $v);
}
#每次查询的条数
$pageSize = 5000;
#分批导的次数
$pages = ceil($totalNums / $pageSize);
#打开文件流
$fp = fopen($pathName, 'a');
#将数据格式化为CSV格式并写入到文件流中
fputcsv($fp, $headerTitleArr);
#主体内容
$paegNum = 0;
for ($i=0; $i <$pages ; $i++) {
$data = Db::table('t_excle')->limit($paegNum,$pageSize)->field('')->select();
foreach ($data as $fields) {
foreach ($fields as $key => &$v) {
// CSV的Excel支持GBK编码,一定要转换,否则乱码
// 加\"大众\t\"大众防止数字导出时变成科学计数
$v = iconv('utf-8', 'gbk', $v.\"大众\t\"大众);
}
fputcsv($fp, $fields);
//这边可记录下数据的末了一次的位置,便于查看排错定位。
}
unset($data);//开释变量的内存
$paegNum += $pageSize;
}
fclose($fp);
#输出下载链接,url为下载的域名
return $url.$pathName;
}
对付一个要求来说PHP是单线程的,大数据量的导出又是最耗时的,搞不好其他要求就壅塞了。
小数据量的话,可以直接浏览器输出;
大数据量的话,可以天生excle下载链接;推举利用swoole异步框架处理要求。
1.当客服在后台系统点击下载后,可先返回个提示或是天生一条下载记录;
2.在后台异步处理excle导出操作;
3.客服主动刷新页面查看是否有下载链接天生。
再上代码(天生excle直接浏览器输出):
public function downOrderData($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 = '100000'//从数据库获取总量,假设是十万
$perSize = 1000;//每次查询的条数
$pages = ceil($accessNum / $perSize);
$lastId = 0;
for($i = 1; $i <= $pages; $i++) {
$data = Db::table('t_excle')->limit($lastId ,$pageSize)->field('')->select();
foreach($data as $value) {
mb_convert_variables('GBK', 'UTF-8', $value);
fputcsv($fp, $value);
$lastId = $value['id'];
}
unset($data);//开释变量的内存
//刷新输出缓冲到浏览器
ob_flush();
flush();//必须同时利用 ob_flush() 和flush() 函数来刷新输出缓冲。
}
fclose($fp);
exit();
}
PS:更多信息互换,请关照:倒影Amoy
活着便是为了改变天下,难道还有其他缘故原由吗?----乔布斯
请输入图片描述