Laravel Excel加载大Excel文件内存占用过高,如何实现类似Model::chunk的无Import类分块读取?
Laravel Excel加载大Excel文件内存占用过高,如何实现类似Model::chunk的无Import类分块读取?
我太懂你的顾虑了!一次性把几万行Excel全塞进内存,别说10万行的大文件,就算当前的35MB文件都已经让人担心后续的扩展性。而且官方文档里的Chunk Reading看起来绑定了Import类,好像必须要写个专门的导入模型才行,确实不太灵活。
其实不用单独创建Import类,照样能实现类似Model::chunk的分块读取,用Laravel Excel自带的方法就能搞定,给你分享两种实用的方式:
方式一:直接用chunk方法配合匿名回调(最推荐)
这是最贴合你需求的方案,不用定义任何Import类,直接在控制器里就能分块处理:
$filePath = '../public/New_Products_2022-12-23.xlsx'; // 开启分块过滤,每次处理1000行(可根据服务器配置调整) Excel::filter('chunk') ->load($filePath) // 如果你的表头不是第一行,用这个指定表头位置,比如第2行 // ->headerRow(2) ->chunk(1000, function ($batchRows) { // 在这里处理每一批数据,完全和处理集合一样 foreach ($batchRows as $row) { // 你的解析逻辑,比如提取单元格值 $parsedData = [ 'sku' => $row->sku, 'product_name' => $row->product_name, 'price' => $row->retail_price, // 其他需要解析的字段... ]; // 调用API上传解析后的数据 // $this->uploadToOnlineShop($parsedData); } // 可以随时查看当前内存使用情况,验证效果 $memory = round(memory_get_peak_usage(true) / 1024 / 1024, 2); dump("处理完一批共{$batchRows->count()}行,当前内存峰值:{$memory}MB"); });
这个方法的核心是filter('chunk'),它会让Laravel Excel底层用流式读取的方式,每次只把当前批次的行加载到内存,处理完就自动释放,内存占用会大幅降低——就算是10万行的文件,也不会出现内存溢出的问题。你可以根据自己服务器的内存情况调整chunk的参数(比如500或2000),找到速度和内存的平衡点。
方式二:利用原生流式读取(进阶)
如果上面的方法还不够灵活,你可以直接用Laravel Excel底层依赖的库来实现更精细的流式读取,依然依托Laravel Excel的封装,不用自己处理Excel解析细节:
use Maatwebsite\Excel\Excel; use Maatwebsite\Excel\Reader; $reader = app(Reader::class)->create($filePath, Excel::XLSX); $reader->open($filePath); // 跳过表头行(如果需要) $reader->nextRow(); // 逐行读取,手动控制批次 $batchSize = 1000; $currentBatch = []; while ($row = $reader->nextRow()) { $currentBatch[] = $row->toArray(); // 当批次达到指定大小,处理并清空 if (count($currentBatch) === $batchSize) { $this->processBatch($currentBatch); $currentBatch = []; } } // 处理最后一批不足batchSize的数据 if (!empty($currentBatch)) { $this->processBatch($currentBatch); } $reader->close(); // 自定义处理批次的方法 private function processBatch($batch) { foreach ($batch as $row) { // 解析+上传逻辑... } }
这种方式更接近原生的生成器思路,但不用自己从零实现Excel读取,兼容性和稳定性都有保障。
总之,不用纠结必须写Import类,Laravel Excel提供了足够灵活的分块/流式读取能力,完全能满足你先解析再上传的需求~
备注:内容来源于stack exchange,提问作者Marcin
相关产品推荐
相关产品推荐

