C# .NET 5大视频分块上传服务端获取ByteArrayContent问题咨询
解决方案
问题原因
- 异步方法未等待:你之前调用
CopyToAsync未添加await关键字,内存流还未写入完成就调用ToArray,导致拿到的内容不完整 - 客户端缺失必填字段:上传的
ByteArrayContent的ContentDisposition未设置Name属性,导致ASP.NET Core默认表单解析无法识别为文件项,因此Request.Form.Files为空 - 直接读取Body内容无效:
Request.Body存储的是完整的multipart表单报文,包含分隔符、请求头字段等附加内容,不是纯文件字节,直接读取无法直接使用
修正方案
1. 客户端代码调整
给ContentDisposition添加Name属性,同时可补充分块相关参数方便服务端处理:
fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") { FileName = Path.GetFileName(fileName), Name = "uploadChunk" // 表单解析依赖该字段识别文件项 }; // 可选:补充分块标识参数 content.Add(new StringContent("文件唯一ID"), "fileId"); content.Add(new StringContent("当前分块序号"), "chunkIndex"); content.Add(new StringContent("总分块数"), "totalChunk");
2. 服务端配置调整
在Program.cs中添加配置,取消请求大小限制(也可设置为自定义的分块最大值):
builder.WebHost.ConfigureKestrel(options => { // 取消请求大小限制,也可设置为具体数值,单位为字节 options.Limits.MaxRequestBodySize = null; });
3. 服务端分块读取实现(两种可选)
方案一:使用Request.Form.Files(最简单,适合大多数场景)
控制器代码示例:
[HttpPost("api/uploadFile")] [DisableRequestSizeLimit] public async Task<IActionResult> UploadChunk() { // 手动触发表单解析 var form = await Request.ReadFormAsync(); var uploadFile = form.Files.FirstOrDefault(); if (uploadFile == null) { return BadRequest("未获取到上传分块"); } // 读取分块字节 using var chunkMs = new MemoryStream(); await uploadFile.CopyToAsync(chunkMs); var chunkBytes = chunkMs.ToArray(); // 此处添加分块处理逻辑:比如按文件标识+分块序号存储临时文件,所有分块上传完成后合并为完整文件 return Ok(); }
方案二:使用MultipartReader(低内存占用,适合超大分块场景)
无需依赖表单解析,直接从请求流读取内容:
[HttpPost("api/uploadFile")] [DisableRequestSizeLimit] public async Task<IActionResult> UploadChunk() { var contentType = MediaTypeHeaderValue.Parse(Request.ContentType); var boundary = MultipartRequestHelper.GetBoundary(contentType, 1024); var reader = new MultipartReader(boundary, Request.Body); var section = await reader.ReadNextSectionAsync(); byte[] chunkBytes = null; while (section != null) { if (ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out var cd) && cd.IsFileDisposition()) { using var chunkMs = new MemoryStream(); await section.Body.CopyToAsync(chunkMs); chunkBytes = chunkMs.ToArray(); break; } section = await reader.ReadNextSectionAsync(); } if (chunkBytes == null) { return BadRequest("未获取到上传分块"); } // 此处添加分块处理逻辑 return Ok(); }
提示:实际生产使用时,建议客户端额外上传文件唯一标识、当前分块序号、总分块数三个参数,服务端可根据参数暂存分块,所有分块上传完成后按序号合并即可得到完整文件。
内容的提问来源于stack exchange,提问作者Joe Morgan
相关产品推荐
相关产品推荐

