.NET Core 3.1上传大文件时Request.Form.Files报InvalidOperationException如何解决
问题描述
使用Postman测试POST文件上传接口时,1MB左右的小文件上传功能正常,上传8MB及以上的大文件会抛出异常。
报错信息
报错代码行:
await Request.Form.Files[0].CopyToAsync(ms).ConfigureAwait(false);
错误详情:
Request.Form.Files = 'Request.Form.Files' threw an exception of type 'System.InvalidOperationException'
运行环境
当前项目为.NET Core 3.1应用
接口原始代码
[HttpPost("File")] [SAPolicy(SAPolicy.Admin, SAPolicy.ConsumerApp)] public async Task<IActionResult> PostFile() { FileContractRequest fileContract = null; try { if (Request.ContentLength > 0) { using (var ms = new MemoryStream()) { await Request.Form.Files[0].CopyToAsync(ms).ConfigureAwait(false); var data = ms.ToArray(); var newFileContract = new FileContractRequest() { ContentType = Request.Form.Files[0].ContentType, Name = Path.GetFileName(Request.Form.Files[0].FileName), Length = data.LongLength.ToString(), CreationDate = DateTime.UtcNow, Data = data }; fileContract = newFileContract; } } else { return new StandardResponse<FileContractResponse>(HttpStatusCode.NotAcceptable, null).Result; } } catch (Exception ex) { throw ex; } var result = await _fileService.PostFile(fileContract).ConfigureAwait(false); return new StandardResponse<FileContractResponse>(HttpStatusCode.OK, result).Result; }
补充报错截图


修复方案
这个问题是.NET Core默认的请求大小、表单大小限制导致的,按以下步骤修改即可:
1. 调整配置限制
根据你的部署方式选择对应配置,按需调整大小上限,以下示例设置最大支持100MB文件上传:
全局配置(Startup.cs的ConfigureServices方法中添加)
// 调整表单提交大小限制 services.Configure<FormOptions>(options => { options.MultipartBodyLengthLimit = 100 * 1024 * 1024; }); // Kestrel运行时调整请求体大小限制 services.Configure<KestrelServerOptions>(options => { options.Limits.MaxRequestBodySize = 100 * 1024 * 1024; });
IIS部署额外配置
在项目根目录的web.config中添加节点:
<system.webServer> <security> <requestFiltering> <!-- 单位为字节,对应100MB --> <requestLimits maxAllowedContentLength="104857600" /> </requestFiltering> </security> </system.webServer>
单接口配置(无需全局修改的场景)
直接在上传接口的Action上添加特性即可:
[RequestSizeLimit(100 * 1024 * 1024)] [RequestFormLimits(MultipartBodyLengthLimit = 100 * 1024 * 1024)]
2. 代码优化建议
建议直接用IFormFile接收上传文件,写法更简洁也能避免直接操作Request.Form可能出现的异常,修改后接口代码如下:
[HttpPost("File")] [SAPolicy(SAPolicy.Admin, SAPolicy.ConsumerApp)] [RequestSizeLimit(100 * 1024 * 1024)] [RequestFormLimits(MultipartBodyLengthLimit = 100 * 1024 * 1024)] public async Task<IActionResult> PostFile(IFormFile file) { if (file == null || file.Length == 0) { return new StandardResponse<FileContractResponse>(HttpStatusCode.NotAcceptable, null).Result; } FileContractRequest fileContract = null; try { using (var ms = new MemoryStream()) { await file.CopyToAsync(ms).ConfigureAwait(false); var data = ms.ToArray(); var newFileContract = new FileContractRequest() { ContentType = file.ContentType, Name = Path.GetFileName(file.FileName), Length = data.LongLength.ToString(), CreationDate = DateTime.UtcNow, Data = data }; fileContract = newFileContract; } } catch (Exception ex) { // 此处可添加日志记录异常信息 throw; } var result = await _fileService.PostFile(fileContract).ConfigureAwait(false); return new StandardResponse<FileContractResponse>(HttpStatusCode.OK, result).Result; }
注意:原有代码中catch块的throw ex;会清空异常堆栈信息,改为throw;即可保留完整堆栈方便排查问题。
内容的提问来源于stack exchange,提问作者rajan.sngh
相关产品推荐
相关产品推荐

