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<kestrelserveroptions></kestrelserveroptions>设置
Limits.MaxRequestBodySize(单位字节) 同时调用
builder.Services.Configure<formoptions></formoptions>设置
ValueLengthLimit和
MultipartBodyLengthLimit(后者影响整个 multipart 总大小) 若部署在 IIS,还需在
web.config添加
<requestlimits maxallowedcontentlength="2147483648"></requestlimits>(单位字节) 注意: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)
真正卡住人的往往不是怎么写上传逻辑,而是边界情况:超时配置漏一处、路径没校验、并发写同一个临时文件、反向代理限制没同步。这些地方一错,表现就是“明明代码一样却传不上”。
