ASP.NET Core 中通过 RequestSizeLimit
控制上传大小
在 ASP.NET Core 服务端限制上传文件大小,最直接的方式是使用
RequestSizeLimit特性。它作用于整个请求体(包括表单字段和文件),单位是字节。
常见错误是只改了前端或中间件配置,却漏掉这个全局限制,导致大文件上传直接返回 413 Payload Too Large 错误,且不进控制器逻辑。
在控制器方法上加:[RequestSizeLimit(20_000_000)](限制 20MB) 若需全局生效,在
Program.cs中配置:
app.Use((context, next) =>
{
context.Features.Get<IHttpMaxRequestBodySizeFeature>().MaxRequestBodySize = 20_000_000;
return next();
});
注意:该设置必须在 UseRouting之后、
UseEndpoints之前注册,否则无效
IIS 或 Kestrel 部署时的额外限制
即使代码里设了
RequestSizeLimit,实际部署后仍可能被宿主服务器拦截——这是最容易被忽略的一环。
IIS 默认限制为 30MB(28.6MiB),Kestrel 默认仅 30MB(31,457,280 字节)。超出会直接断连,连 413 都不返回。
IIS:修改web.config的
<requestlimits maxallowedcontentlength="20971520"></requestlimits>(单位字节) Kestrel:在
Program.cs中配置
options.Limits.MaxRequestBodySize = 20_000_000;Linux + Nginx:还需检查
client_max_body_size指令是否同步调整
区分单文件 vs 总请求体大小的判断逻辑
RequestSizeLimit限制的是整个 HTTP 请求体,不是单个文件。如果表单含多个文件+文本字段,总大小超限就会失败,但你无法从框架层直接知道是哪个文件导致的。
真正需要“单文件大小校验”的场景,得手动解析
IFormFile: 在 Action 中遍历
Request.Form.Files对每个
IFormFile检查
file.Length,再抛出明确提示(如
BadRequest("文件 xxx 超过 10MB"))
注意:必须先调用 file.OpenReadStream()或访问
Length才能触发底层读取,否则某些情况下长度可能为 0
大文件上传时的内存与流处理风险
用
IFormFile.CopyToAsync直接保存,小文件没问题;但上传 100MB 文件时,若未指定缓冲区或未用流式处理,容易触发
OutOfMemoryException或阻塞线程。 避免
file.CopyTo(同步阻塞);优先用
CopyToAsync并传入
new FileStream(...)不要把整个
IFormFile读进
MemoryStream,尤其在高并发下 考虑搭配
DisableRequestSizeLimit+ 手动流校验,适用于需支持超大文件但又要求精准控制的场景
真正麻烦的从来不是设个数字,而是所有环节——代码限制、宿主配置、反向代理、客户端行为、流处理方式——必须全部对齐,缺一不可。
