thinkphp5导出excel需分路径处理:大数据量用csv+cursor()避免内存爆炸,加bom头防中文乱码;小批量用phpspreadsheet批量写入、禁用公式引擎、设正确响应头并exit,严禁使用已废弃的phpexcel。

ThinkPHP5 生成 Excel 表格导出不是“装个包调个方法就完事”,核心卡点在**内存爆炸**和**中文乱码/格式崩溃**——直接 Db::select() 查 2 万条再喂给 PhpSpreadsheet,99% 触发 Fatal error: Allowed memory size exhausted;用 HTML 表格伪造 Excel,打开就是编码错误或样式全丢。
必须按数据量、格式要求、稳定性分路径处理,没有银弹。
大数据量(>5000 行)必须走 CSV + cursor()
Excel 格式不支持流式写入,PhpSpreadsheet 内部会缓存全部单元格对象。1 万行 ≈ 300MB 内存占用,线上服务扛不住。
- 用
Db::name('user')->cursor()替代select(),逐行 fetch,内存恒定在几 MB - 输出前必须加 BOM 头:
echo "\xEF\xBB\xBF";,否则 Excel 默认 ANSI 解码,中文全变问号 - 用原生
fputcsv(),字段顺序、空值转空字符串、引号/换行自动转义都由它兜底,别用框架封装的 exportCsv -
ob_end_clean()必须调用,否则响应体开头混入空白或 HTML,CSV 文件损坏
小批量(
如果业务明确要求公式、条件格式、合并单元格,PhpSpreadsheet 是唯一靠谱选择,但初始化和写入节奏必须控制。
- 禁用计算引擎:
$spreadsheet->setCalculationEngine(new \PhpOffice\PhpSpreadsheet\Calculation\Calculation());,否则含公式的文件读写时 CPU 爆表 - 绝对不要逐单元格赋值:
$sheet->setCellValue('A'.$row, $val)写 1 万行 = 1 万个 PHP 对象,内存翻倍;改用fromArray($chunk, null, 'A2')批量写入 - 分块写入:每 500 行调一次
ob_flush()推送缓冲区,$writer->save('php://output')只在最后调一次 - 必须加完整响应头:
Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,Content-Disposition: attachment; filename="xxx.xlsx",并exit
千万别再用 new \PHPExcel() —— 已废弃且 TP5.1+ 不兼容
PHPExcel 自 2017 年起停止维护,官方明确迁移至 phpoffice/phpspreadsheet。所有教程里出现 new \PHPExcel() 或 vendor('PHPExcel.PHPExcel') 的写法,在 TP5.1+ 中大概率报错或静默失败。
- Composer 安装必须是:
composer require phpoffice/phpspreadsheet - 命名空间必须是:
use PhpOffice\PhpSpreadsheet\Spreadsheet;,不是PHPExcel - 导出后不
exit或漏掉ob_end_clean(),响应体里混入框架 debug 信息,Excel 文件打不开
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











