IFormFile为null的根本原因是请求未进入模型绑定管道:必须使用multipart/form-data编码、禁用[FromBody]、参数名与FormData字段严格一致、Swagger需点“Choose File”上传。

IFormFile 总是 null?不是代码错了,是请求根本没进模型绑定管道
前端没设 enctype="multipart/form-data",浏览器就当普通表单发 application/x-www-form-urlencoded,文件字段直接被丢弃。后端参数加了 [FromBody] 更是雪上加霜——JSON 绑定器根本解析不了 multipart 数据,直接 400 返回,连断点都进不去。
常见踩坑点:
- HTML 表单漏写
enctype="multipart/form-data" - JS fetch 用
JSON.stringify()发送,而不是FormData实例 - Swagger 测试时手动填字符串或 Base64,没点「Choose File」——它不支持模拟二进制流
- 前端
append('upload', file),后端却写IFormFile file:key 名必须完全一致(默认是file)
怎么安全保存 IFormFile 到磁盘
别拼 file.FileName 直接进路径——它由浏览器控制,可伪造为 ../../../web.config 或 shell.php.exe,导致目录穿越或远程执行。
正确做法:
- 只取扩展名:
Path.GetExtension(file.FileName).ToLowerInvariant(),再比对白名单(如".pdf"、".xlsx") - 生成全新文件名:
$"{Guid.NewGuid():N}{ext}"或Path.GetRandomFileName() + ext - 目标路径用
Path.Combine(uploadRoot, safeName)拼接,uploadRoot必须是绝对路径(如_env.WebRootPath),且提前Directory.CreateDirectory() - 大文件必须流式写入:
using var fs = File.Create(path); await file.CopyToAsync(fs);,禁用file.OpenReadStream().ToArray()
上传超 128 MB 就报 413?改三处配置才生效
ASP.NET Core 默认在 Kestrel 层就拦截整个请求体(128 MB),超过直接 413.13,中间件和 Controller 都收不到请求。
必须同步调整:
-
Program.cs中配 Kestrel:builder.Services.Configure<kestrelserveroptions>(o => o.Limits.MaxRequestBodySize = 500_000_000);</kestrelserveroptions> - 同时配 FormOptions:
builder.Services.Configure<formoptions>(o => o.MultipartBodyLengthLimit = 500_000_000);</formoptions> - 若部署在 IIS,还得在
web.config加:<requestLimits maxAllowedContentLength="500000000" />
多文件上传与类型校验的实用边界
IFormFileCollection 或 IEnumerable<iformfile></iformfile> 接收多文件时,name 属性必须一致(如 <input name="files" multiple>),且表单仍需 enctype="multipart/form-data"。
校验不能只信扩展名或 ContentType(易伪造),但可辅助判断:
- 总大小限制(如所有文件加起来 ≤ 100 MB):
files.Sum(f => f.Length) - 扩展名白名单 +
ContentType粗筛(如"image/jpeg"对应".jpg") - 真要防恶意内容,得在保存后调用杀毒 SDK 扫描,或交由云存储(如 Azure Blob)自带的病毒扫描服务
最常被忽略的是:上传路径权限。千万别让应用进程对上传目录有执行权限,也别把上传目录放在 wwwroot 下直接可访问——应存到独立非 Web 可达路径,再通过专用 Action(如 Download/{id})控制访问逻辑。


















