excel插件消耗过大通过csv取代excel,压缩成zip方便下载
/*
*
* @param string $sql 需要导出的数据SQL
* @param string $mark 生成文件的名字前缀
* @param bool $is_multiple 是否要生成多个CSV文件
* @param int $limit 每隔$limit行,刷新输出buffer,以及每个CSV文件行数限制
*
*/
function putCsv($list, $mark, $is_multiple=0, $limit=100000)
{
set_time_limit(0);
// header('Content-Type: application/vnd.ms-excel;charset=utf-8');
// header('Content-Disposition: attachment;filename="' . $mark . '"');
// header('Cache-Control: max-age=0');
// 每隔$limit行,刷新一下输出buffer,也可以控制多csv文件生成的行数限制
// buffer计数器
$file_num = 0; //文件名计数器
$row_num = 0;
$fileNameArr = array();
// 逐行取出数据,不浪费内存
$dir = './';
// var_dump(file_exists('./csv'),file_exists('csv/')); die;
if(!file_exists('./csv')){
$dir = './public/';
}
$mark.=date('YmdHis', time());
$fp = fopen($dir.'csv/'.$mark .'_'.$file_num .'.csv', 'w'); //生成临时文件
$fileNameArr[] = $dir.'csv/'.$mark .'_'.$file_num .'.csv';
fwrite($fp, chr(0xEF).chr(0xBB).chr(0xBF));//转码,防止乱码
foreach ($list as $a) {
$row_num++;
if ($limit <= $row_num) {
//刷新一下输出buffer,防止由于数据过多造成问题
if(ob_get_level()>0) ob_flush(); flush();
$row_num = 0;
$file_num++;
if($is_multiple>0){
fclose($fp); //每生成一个文件关闭
$fp = fopen($dir.'csv/'.$mark .'_'.$file_num .'.csv', 'w');
$fileNameArr[] = $dir.'csv/'.$mark .'_'.$file_num .'.csv';
fwrite($fp, chr(0xEF).chr(0xBB).chr(0xBF));//转码,防止乱码
}
}
fputcsv($fp, $a);
}
fclose($fp); //每生成一个文件关闭
// getZip('test',$fileNameArr); //生成zip文件
$filename = $dir.'zip/'.$mark.'_' . date('YmdHis', time()).'.zip';
$zip = new ZipArchive();
$res = $zip->open($filename, ZipArchive::CREATE);
if ($res === TRUE) {
foreach ($fileNameArr as $file) {
//这里直接用原文件的名字进行打包,也可以直接命名,需要注意如果文件名字一样会导致后面文件覆盖前面的文件,所以建议重新命名
$new_filename = substr($file, strrpos($file, '/') + 1);
$zip->addFile($file, $new_filename);
}
}
//关闭文件
$zip->close();
return $filename;
}
调用方法
$list = Db::name("log")->select()->toArray();
$mark = '日志导出';//生成文件前缀
putCsv($list,$mark);