You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.20 10:42:59