PHP---导出百万大数据【解决方案】
最近开发项目,遇到一个问题,通常导出数据我们都会使用 PHPExcel 来导出数据,但是遇到大数据,这个方法就不行了。
例如:我的项目,3.5W个学生信息,需要导出做数据备份,使用【PHPExcel】来导出就不行了,需要另谋它法:
不考虑PHPExcel就只能考虑导出CSV:
具体实现思路:
按照一定的数量,例如:5000条,导出CSV文件,多个CSV文件进行压缩为ZIP,最后导出ZIP里面就有所有数据。例如:3.5w条数据,最终有5个CSV文件,生成一个ZIP压缩文件。
代码:
public function exportCSV() { $limit = 5000;//每次只从数据库取50000条以防变量缓存太大 // buffer计数器 $cnt = 0; $xlsTitle = ['序号','姓名','性别']; /******************** 调整位置开始 ***************************/ $sqlCount = 3000; // 这里需要查询出总条数 /******************** 调整位置结束 ***************************/ $fileName = iconv('utf-8', 'gb2312', 'students');//文件名称 $fileName = $fileName . date('_YmdHis');// 文件名称可根据自己情况设定 $zipname = 'zip-' . $fileName . ".zip"; // 输出Excel文件头,可把user.csv换成你要的文件名 header('Content-Type: application/vnd.ms-excel;charset=utf-8'); header('Content-Disposition: attachment;filename="' . $zipname . '"'); header('Cache-Control: max-age=0'); $fileNameArr = array(); // 逐行取出数据,不浪费内存 for ($i = 0; $i < ceil($sqlCount / $limit); $i++) { $fp = fopen($fileName . '_' . ($i+1) . '.csv', 'w'); //生成临时文件 // chmod('attack_ip_info_' . $i . '.csv',777);//修改可执行权限 $fileNameArr[] = $fileName . '_' . ($i+1) . '.csv'; // 将数据通过fputcsv写到文件句柄 fputcsv($fp, $xlsTitle); $start = $i * $limit; /******************** 调整位置开始 ***************************/ $dataArr = $this->model->getList($start,$limit); // 每次查询limit条数据 /******************** 调整位置结束 ***************************/ foreach ($dataArr as $a) { $cnt++; if ($limit == $cnt) { // 刷新一下输出buffer,防止由于数据过多造成问题 ob_flush(); flush(); $cnt = 0; } fputcsv($fp, $a); } fclose($fp); // 每生成一个文件关闭 } // 进行多个文件压缩 $zip = new \ZipArchive(); $zip->open($zipname, $zip::CREATE); // 打开压缩包 foreach ($fileNameArr as $file) { $zip->addFile($file, basename($file)); // 向压缩包中添加文件 } $zip->close(); // 关闭压缩包 foreach ($fileNameArr as $file) { unlink($file); // 删除csv临时文件 } // 输出压缩文件提供下载 header("Cache-Control: max-age=0"); header("Content-Description: File Transfer"); header("Content-Type: application/zip"); // zip格式 header("Content-Transfer-Encoding: binary"); header('Content-Length: ' . filesize($zipname)); @readfile($zipname); // 输出文件 unlink($zipname); // 删除压缩包临时文件 }
参考:
https://cloud.tencent.com/developer/article/1990268
打完收工!