ASP.NET Core Web API接收multipart/form-data文件需用IFormFile参数并确保前后端key名一致;须配置Kestrel、FormOptions及反向代理的上传限制;保存时禁用原始文件名、异步写入并确保目录可写;返回uploadId供前端轮询进度。

ASP.NET Core Web API如何接收 multipart/form-data 文件
ASP.NET Core 默认能解析 multipart/form-data 请求,但必须显式启用模型绑定支持——否则 IFormFile 参数会为 null 或抛出 400 错误。关键不是“能不能”,而是“有没有配对的接收方式”。
- 控制器方法参数必须是
IFormFile(单文件)或IFormFileCollection(多文件),不能用Stream或byte[]直接绑定 -
前端
FormData的 key 名必须和 Action 参数名完全一致,例如form.append("file", input.files[0])→ 后端用IFormFile file - 若使用
[FromForm],只在复杂模型中需要;单个IFormFile参数可省略该特性 - .NET 6+ 默认允许最大 128 MB 文件,超出需配置
MaxRequestBodySize和FormOptions.ValueLengthLimit
如何配置大文件上传限制(避免 413 Payload Too Large)
默认限制太小,上传几十 MB 就失败。错误信息通常是 HTTP Error 413.13 - Payload Too Large 或日志里出现 Request body too large。这不是代码写错了,是没调服务层阈值。
- 在
Program.cs中调用builder.Services.Configure设置Limits.MaxRequestBodySize(单位字节) - 同时调用
builder.Services.Configure设置ValueLengthLimit和MultipartBodyLengthLimit(后者影响整个 multipart 总大小) - 若部署在 IIS,还需在
web.config添加(单位字节) - 注意:Kestrel 配置仅对 Kestrel 生效;反向代理(如 Nginx)也有自己的 client_max_body_size 限制,必须同步调整
IFormFile.CopyToAsync() 保存文件时要注意什么
直接调用 CopyToAsync() 看似简单,但容易忽略路径安全、并发冲突和磁盘权限问题。
- 永远不要拼接原始
IFormFile.FileName构造路径——它可能含../或非法字符,应使用Path.GetRandomFileName()生成新名 - 保存前检查目标目录是否存在,用
Directory.CreateDirectory()确保路径可写 - 若高并发上传同名临时文件,建议加
Guid.NewGuid()前缀或用Path.GetTempFileName() - 异步保存时别忘了 await,否则可能提前释放流导致写入不全;也不要调用
CopyTo()(同步阻塞)
如何返回上传结果并支持进度提示(非 SignalR 场景)
Web API 本身不维护连接状态,所以“实时进度”只能靠客户端轮询或前端用 XMLHttpRequest.upload.onprogress 监听。后端只需做两件事:快速响应 + 提供可查的上传 ID。
- 上传成功后返回 JSON,包含唯一
uploadId和文件元数据(如fileName、size、url) - 若需查询状态(例如后台异步转码),把
uploadId存进内存字典或 Redis,并提供 GET/api/uploads/{id}接口 - 避免在上传接口里做耗时操作(如图片压缩)——先存原图,再发后台任务处理
- 前端用
fetch时需设置body: formData且不手动设Content-Type(浏览器会自动加 boundary)
真正卡住人的往往不是怎么写上传逻辑,而是边界情况:超时配置漏一处、路径没校验、并发写同一个临时文件、反向代理限制没同步。这些地方一错,表现就是“明明代码一样却传不上”。










