一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

ThinkPHP导入Excel如何批量处理多个文件导入教程

时间:2026-07-28 07:04:48 编辑:袖梨 来源:一聚教程网

ThinkPHP导入多个Excel文件需逐个校验、解析与入库:上传时用multiple接收并验证格式和大小;解析时显式指定读取器、禁用样式、分页读取、保留空单元格;入库时按400行分批事务插入且文件间错误隔离。

ThinkPHP导入Excel时需要同时处理多个上传文件,比如用户一次选了3个.xlsx文件要入库,每个文件结构一致但数据独立,必须逐个解析、清洗、分批插入且不能互相干扰。

上传阶段:接收多个文件并校验格式

在表单中设置 multiple 属性:<input type="file" name="files[]" multiple accept=".xlsx,.xls">,后端用 request()->file('files') 获取文件数组。

遍历每个文件,先用 pathinfo($file->getInfo()['name'], PATHINFO_EXTENSION) 提取真实后缀,转大写后判断是否为 【XLSX 或 XLS】;拒绝 .csv、.txt 等非 Excel 格式,phpspreadsheet 默认不支持 CSV 读取,强行加载会直接报错。

对每个文件调用 $file->validate(['size' => 10 * 1024 * 1024, 'ext' => ['xlsx', 'xls']])->move(ROOT_PATH . 'uploads/excel/'),单个文件限制 10MB,避免上传超大文件拖垮整个批次。

立即学习“PHP免费学习笔记(深入)”;

解析阶段:逐个流式读取,跳过空行与样式

对每个已移动成功的文件路径,执行以下操作:

第一步:用 IOFactory::createReader($readerType) 显式创建 Reader,其中 $readerType = $ext === 'xlsx' ? 'Xlsx' : 'Xls'【绝不能用 IOFactory::load() 全自动猜测格式】,它会读文件头试多种解析器,容易把 .xls 误判成 .xlsx 导致解析失败。

第二步:调用 $reader->setReadDataOnly(true) 关闭样式、公式、注释等非数据内容解析,内存占用可降低 60% 以上,尤其对带条件格式的报表类 Excel 效果明显。

第三步:获取活动工作表后,用 $worksheet->getRowIterator(1, 500) 控制每次只读 500 行——这是关键,不设上限会一次性加载整表,10 万行 Excel 直接触发 PHP 内存溢出。

第四步:遍历每行单元格时,必须加 $cellIterator->setIterateOnlyExistingCells(false),否则 Excel 中中间列为空时会被跳过,导致后续列全部左移,字段错位。

第五步:组装行数据后,用 array_filter($rowData) 判断是否全空,只保留至少有一个非空值的行;别只检查第一列,有些模板首列是序号,填了但其他列为空。

入库阶段:事务包裹 + 分批控制 + 错误隔离

方法一:单文件事务独立封装

每个文件解析出的所有有效行,按 400 行一组切片:$chunks = array_chunk($allRows, 400);对每个 chunk,用 Db::transaction(function () use ($chunk) { Db::name('user')->insertAll($chunk); }); 包裹——这样即使某个 chunk 插入失败(如唯一索引冲突),只回滚当前 chunk,不影响同一文件其余数据。

方法二:跨文件错误不传播

外层不用大事务包所有文件。用 foreach 遍历文件列表,每个文件单独 try/catch;捕获到 Throwable 时记录日志并继续下一个文件,【绝不 throw 向上抛】,否则一个文件出错会导致后续全部跳过。

方法三:字段映射硬编码防错位

第一行必须是表头,用 $worksheet->getCellByColumnAndRow($col, 1)->getValue() 逐列读取,trim(str_replace(["n","r"], '', $header)) 清洗后再匹配预设字段映射表,例如 ['用户姓名' => 'real_name', '手机号' => 'mobile'];没匹配上的列直接丢弃,防止 Excel 多列导致 insertAll 字段数与表结构不一致。

热门栏目