.NET中如何设置Multipart分段上传的文件最大体积限制
为什么FormOptions配置不生效
FormOptions的MultipartBodyLengthLimit限制仅作用于ASP.NET Core自带的表单解析流程,也就是你用Request.Form、IFormFile接收上传内容时才会触发校验。你现在直接用MultipartReader读取原始请求Body,完全绕开了框架自带的表单解析逻辑,所以这个配置自然不会生效。
不需要把流全读入内存就能校验大小
你可以在读取流写入目标存储(磁盘/对象存储等)的过程中实时统计已读取的字节数,超过对应上限就直接终止操作即可,全程不会把整个文件加载到内存。
具体实现方案
首先定义扩展名和大小限制的映射规则,示例如下:
// 单位:字节,规则可自行调整 private readonly Dictionary<string, long> _sizeLimitPerExtension = new(StringComparer.OrdinalIgnoreCase) { { ".pdf", 5 * 1024 * 1024 }, // PDF最大5MB { ".jpg", 2 * 1024 * 1024 }, // JPG图片最大2MB { ".txt", 1 * 1024 * 1024 } // 文本文件最大1MB }; // 未匹配到扩展名的默认最大限制 private const long DefaultSizeLimit = 3 * 1024 * 1024;
然后改造你的上传接口逻辑,增加流式大小校验:
[HttpPost] public async Task<IActionResult> Post() { var request = HttpContext.Request; // 原有ContentType校验逻辑保留 if (!request.HasFormContentType || !MediaTypeHeaderValue.TryParse(request.ContentType, out var mediaTypeHeader) || string.IsNullOrEmpty(mediaTypeHeader.Boundary.Value)) { return new UnsupportedMediaTypeResult(); } var reader = new MultipartReader(mediaTypeHeader.Boundary.Value, request.Body); var section = await reader.ReadNextSectionAsync(); while (section != null) { var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out var contentDisposition); if (hasContentDispositionHeader && contentDisposition.DispositionType.Equals("form-data") && !string.IsNullOrEmpty(contentDisposition.FileName.Value)) { var fileName = contentDisposition.FileName.Value; var extension = Path.GetExtension(fileName); // 获取对应扩展名的大小限制 if (!_sizeLimitPerExtension.TryGetValue(extension, out var maxSize)) { maxSize = DefaultSizeLimit; } long totalRead = 0; var buffer = new byte[4096]; // 替换为你实际要写入的目标流,比如本地文件流、对象存储上传流等 var targetStream = new MemoryStream(); int read; // 边读边统计字节数 while ((read = await section.Body.ReadAsync(buffer)) > 0) { totalRead += read; if (totalRead > maxSize) { return BadRequest($"文件大小超过限制,{extension}格式文件最大允许{maxSize/1024/1024}MB"); } await targetStream.WriteAsync(buffer.AsMemory(0, read)); } // 校验通过后执行上传逻辑 await _uploader.UploadAsync(targetStream); return Ok(); } section = await reader.ReadNextSectionAsync(); } return BadRequest("No files data in the request."); }
额外注意点
如果你使用了IIS、Nginx等反向代理服务,还需要同步修改反向代理层的上传大小限制:
- IIS需要在
web.config中配置maxAllowedContentLength参数 - Nginx需要配置
client_max_body_size参数
否则请求还没到达.NET服务就会被反向代理拦截。
内容的提问来源于stack exchange,提问作者Craig
相关产品推荐
相关产品推荐

