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

Laravel使用maatwebsite/excel导入Excel报errno=21错误如何解决

错误原因说明

file_put_contents(): read of 8192 bytes failed with errno=21 Is a directory 错误的本质是程序尝试向路径写入内容时,该路径指向的是目录而非普通文件。在maatwebsite/excel导入大体积Excel场景下,该错误绝大多数由临时缓存目录配置错误、权限异常或大文件分块策略缺失导致。

排查步骤
  • 检查maatwebsite/excel的临时缓存路径配置,确认配置值为合法的可写目录,而非文件路径
  • 验证上传文件的完整性:确认php.ini的上传限制参数适配当前Excel文件大小,避免文件上传截断
  • 检查Laravel storage目录的权限,确认web服务器运行用户对storage/framework/下的子目录有读写权限
  • 确认导入类是否配置了大文件分块读取逻辑,避免全量加载文件触发缓存异常
解决方案

1. 修正临时缓存目录配置

首先发布扩展的配置文件:

php artisan vendor:publish --provider="Maatwebsite\Excel\ExcelServiceProvider"

打开生成的config/excel.php文件,修改导入临时路径配置:

'import' => [
    // 其他配置不变
    'temporary_path' => storage_path('framework/excel_temp'),
],

手动创建对应目录并配置权限:

mkdir -p storage/framework/excel_temp
chmod -R 775 storage/framework/excel_temp
# 下方用户组替换为你实际的web服务器运行用户,如nginx、apache等
chown -R www-data:www-data storage/framework/excel_temp

2. 调整PHP上传与运行配置

修改php.ini配置文件,适配大文件导入需求:

; 单文件上传上限调整为大于你的Excel文件大小
upload_max_filesize = 100M
; POST请求体上限匹配上传大小
post_max_size = 100M
; 内存限制适配分块读取需求
memory_limit = 256M
; 脚本最大执行时间调整为足够完成导入
max_execution_time = 300

修改完成后重启web服务与php-fpm服务生效。

3. 开启分块导入降低资源占用

修改你的UsersImport导入类,实现WithChunkReading接口开启分块处理:

<?php

namespace App\Imports;

use Maatwebsite\Excel\Concerns\ToModel;
use Maatwebsite\Excel\Concerns\WithChunkReading;

class UsersImport implements ToModel, WithChunkReading
{
    // 原有导入逻辑保持不变
    
    /**
     * 定义分块大小,可根据服务器配置调整为500-2000区间
     */
    public function chunkSize(): int
    {
        return 1000;
    }
}

4. 优化控制器导入逻辑

调整控制器代码,增加文件有效性校验,避免路径解析错误:

public function importData(Request $request)
{
    try {
        $file = $request->file('file');
        if (!$file->isValid()) {
            throw new \Exception('上传文件不合法,请重新上传');
        }
        Excel::import(new UsersImport, $file->getRealPath());
        return redirect()->back()->with('success', 'Record Imported Successfully');
    }catch (\Exception $e){
        // 开发环境可打开下方注释打印异常堆栈方便排查
        // dd($e->getMessage(), $e->getTraceAsString());
        return redirect()->back()->with('error', $e->getMessage());
    }
}

内容的提问来源于stack exchange,提问作者Ch Bilal Ahmed

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 03:06:01