C# API上传超过3MB文件时[FromBody]参数中byte[]为空如何解决
问题排查与解决方案
第一步:先确认错误根源
在服务端Upload接口开头加日志,输出ModelState.IsValid的值以及ModelState.Errors里的所有异常信息,90%以上的概率你会看到JSON反序列化失败或者请求长度超限的明确报错,而非无理由的doc字段为null。
第二步:补全服务端web.config缺失的配置
你目前只配置了请求头的大小限制,缺了两个核心的请求大小配置:
- 配置system.web节点的请求最大长度(单位为KB,以下配置放开到30MB)
<system.web> <httpRuntime targetFramework="4.7.1" maxRequestLength="30720" /> </system.web>
- 补全system.webServer下requestLimits的整体请求大小限制(单位为字节,和上面30MB对应)
<system.webServer> <security> <requestFiltering> <requestLimits maxAllowedContentLength="31457280"> <headerLimits> <add header="Content-type" sizeLimit="30000000" /> </headerLimits> </requestLimits> </requestFiltering> </security> </system.webServer>
- 放开JSON序列化的长度限制,默认JSON反序列化的数组长度、最大字符数都有4M左右的默认限制,添加如下配置:
<system.web.extensions> <scripting> <webServices> <jsonSerialization maxJsonLength="2147483647"/> </webServices> </scripting> </system.web.extensions>
如果你的WebAPI用的是Newtonsoft.Json作为序列化组件,还要在WebApiConfig.cs的Register方法里加如下配置,放开数组长度限制:
config.Formatters.JsonFormatter.SerializerSettings.MaxArrayLength = int.MaxValue;
第三步:优化上传方式(长期方案)
你当前把文件byte[]序列化到JSON里的方式本身有缺陷:byte[]转JSON会自动转成Base64编码,体积直接膨胀33%,很容易触碰到大小限制,大文件上传更推荐用MultipartFormDataContent传输:
客户端改造示例
using (var content = new MultipartFormDataContent()) { content.Add(new StringContent(file.newFileName), nameof(file.newFileName)); content.Add(new StringContent(file.folderPath), nameof(file.folderPath)); content.Add(new StringContent(file.fileTags), nameof(file.fileTags)); content.Add(new ByteArrayContent(file.doc), nameof(file.doc), file.newFileName); var responseMessage = this.Client.PostAsync("/Upload", content).Result; // 其余逻辑不变 }
服务端改造示例
[HttpPost] [Route("Upload")] public async Task<IHttpActionResult> SaveFileToSharePointStream() { if (!Request.Content.IsMimeMultipartContent()) return BadRequest("请用表单格式上传"); var provider = await Request.Content.ReadAsMultipartAsync(); var newFileName = provider.FormData.Get(nameof(SharepointFileUploadRequest.newFileName)); var folderPath = provider.FormData.Get(nameof(SharepointFileUploadRequest.folderPath)); var fileTags = provider.FormData.Get(nameof(SharepointFileUploadRequest.fileTags)); var docContent = provider.Contents.FirstOrDefault(c => c.Headers.ContentDisposition.Name == nameof(SharepointFileUploadRequest.doc)); if (docContent == null) return BadRequest("缺少文件内容"); using (var ms = await docContent.ReadAsStreamAsync()) { var result = await _sharepointBll.SaveFileToSharePointStream(newFileName, ms, folderPath, fileTags); return Ok(result); } }
这种方式完全绕开了JSON序列化的大小限制,上传性能和稳定性都更高。
内容的提问来源于stack exchange,提问作者Adam Schneider
相关产品推荐
相关产品推荐

