PHP导出大数据CSV
匿名 · 更新于 2021/6/28
/** * 导出excel(csv) * @param $sql sql语句 * @param $total 数据总数 * @param $headlist 第一行,列名 * @param $filename 文件名称 * @param $rule 数据处理规则 * @param $psize 数据分段大小(分页数量) 每隔$psize行(一页数据),刷新一下输出buffer,不要太大,也不要太小 */ function export_csv($sql, $total, $headlist, $filename, $rule = [], $params = [], $psize = 1000) { set_time_limit(0); $open_exoprt = true; if($open_exoprt){ header('Content-Type: application/vnd.ms-excel'); header('Content-Disposition: attachment;filename="'.iconv('utf-8', 'gbk', $filename).'.csv"'); header('Cache-Control: max-age=0'); //打开PHP文件句柄,php://output 表示直接输出到浏览器 $fp = fopen('php://output', 'a'); } //输出Excel列名信息 foreach ($headlist as $key => $value) { //CSV的Excel支持GBK编码,一定要转换,否则乱码 $headlist[$key] = iconv('utf-8', 'gbk', $value); } if($open_exoprt){ //将数据通过fputcsv写到文件句柄 fputcsv($fp, $headlist); } //计算最后一页数量 防止当前联合查询机制导致的数据重复 $lastnum = $total % $psize; //计算总页数 $totalpage = ceil($total / $psize); //记录原sql防止每次查询都是第一页数据 $oldsql = $sql; //开始循环分页输出数据 for ($pindex = 1; $pindex <= $totalpage; $pindex++) { $limit = " LIMIT " . ($pindex - 1) * $psize . ',' . $psize.' '; //防止联合查询数据重复 仅查询剩余数量 if($pindex == $totalpage){ $psize = $lastnum; } //替换sql标识 如果不是用oldsql会导致每次查询的都是前1000条 数据重复 $sql = str_replace(['$limit','$psize'],[$limit,$psize],$oldsql); if(empty($params)){ $list = pdo_fetchall($sql); }else{ $list = pdo_fetchall($sql,$params); } if($open_exoprt){ //逐行取出数据,不浪费内存 foreach ($list as $k => $row){ //处理数据 foreach ($row as $key => $value) { $row[$key] = iconv('utf-8', 'gbk', $value); //处理/格式化数据 if(isset($rule[$key])){ foreach ($rule[$key] as $v){ switch ($v['type']){ case 'time': $row[$key] = date($v['format'],$row[$key]); break; case 'string': $row[$key] = $row[$key]."\t"; break; } } } } fputcsv($fp, $row); } } if($open_exoprt){ //刷新一下输出buffer,防止由于数据过多造成问题 ob_flush(); flush(); } } }
