Laravel使用Maatwebsite Excel拆分大Excel做分批导入报错求助
错误原因
你遇到的Array to String conversion报错核心有两个问题:
file_put_contents()方法要求写入内容为字符串格式,你传入的$part是二维数组,PHP无法自动将数组转为字符串写入文件,直接触发类型转换报错- 普通文件写入方法无法生成符合xls/xlsx格式规范的文件,即便没有类型错误,生成的文件也无法被Excel解析器正常读取
修复步骤
1. 提前准备依赖配置
首先确保resources/pending-files目录存在且有读写权限,Linux环境可执行命令创建:mkdir -p resources/pending-files && chmod 755 resources/pending-files
打开config/filesystems.php,在disks数组中新增资源磁盘配置,方便后续导出文件定位:
'resource' => [ 'driver' => 'local', 'root' => resource_path(), ],
2. 创建分块导出类
执行Artisan命令生成导出类:php artisan make:export OrdersChunkExport
导出类内容如下,用于生成带表头的子Excel文件:
<?php namespace App\Exports; use Maatwebsite\Excel\Concerns\FromArray; use Maatwebsite\Excel\Concerns\WithHeadings; class OrdersChunkExport implements FromArray, WithHeadings { protected $rows; protected $headings; public function __construct(array $rows, array $headings) { $this->rows = $rows; $this->headings = $headings; } public function array(): array { return $this->rows; } public function headings(): array { return $this->headings; } }
3. 替换控制器代码
use App\Exports\OrdersChunkExport; use Maatwebsite\Excel\Facades\Excel; function importBatchFiles(Request $request) { $this->validate($request, [ 'file' => 'required|mimes:xls,xlsx,csv' ]); $file = $request->file('file'); if ($file->isValid()) { $data = Excel::toArray(new \App\Imports\OrdersImport, $file); $inputs = []; foreach($data as $sheet) { foreach($sheet as $row) { $inputs[] = $row; } } // 提取表头 $headings = $inputs[0] ?? []; // 提取除表头外的业务数据 $dataRows = array_slice($inputs, 1); // 按500条拆分数据 $chunks = array_chunk($dataRows, 500); $extension = $file->extension(); $uniqTag = uniqid(); foreach($chunks as $index => $chunk){ // 增加唯一标识避免同时间上传文件重名覆盖 $filename = 'pending-files/'.date('Y-m-d').'-'.$uniqTag.'-'.$index.'.'.$extension; // 调用Maatwebsite导出方法生成合法Excel文件 Excel::store(new OrdersChunkExport($chunk, $headings), $filename, 'resource'); // 此处可补充队列分发逻辑,将文件路径传入队列任务执行导入 // \App\Jobs\ProcessOrderImport::dispatch($filename); } return response()->json(['success' => 'Orders Queued for importing.']); }else{ return response()->json(['error' => 'File upload failed']); } }
优化建议
- 子文件导入完成后及时删除,避免占用服务器磁盘空间
- 如果业务允许,可跳过生成本地子文件的步骤,直接将拆分后的数组块传入队列任务处理入库,节省磁盘IO开销,导入效率更高
- 可根据服务器性能调整单次拆分的条数,不一定限制为500条
内容的提问来源于stack exchange,提问作者Muzafar
相关产品推荐
相关产品推荐

