处理ASP.NET Core 1.0上的大型文件上传

当我在ASP.NET Core中将大文件上传到我的web api时,运行时会在我处理和存储上传的函数被触发之前将文件加载到内存中。 对于大型上传,这会成为一个问题,因为它既慢又需要更多内存。 对于以前版本的ASP.NET ,有一些关于如何禁用缓冲请求的文章,但我无法找到有关如何使用ASP.NET Core执行此操作的任何信息。 是否可以禁用缓冲请求,以便我的服务器上的内存不会一直耗尽?

使用Microsoft.AspNetCore.WebUtilities.MultipartReader因为它…

可以解析任何流[带]最小缓冲。 它一次一个地为您提供每个部分的标题和正文,然后您使用该部分的主体(缓冲区,丢弃,写入磁盘等)执行您想要的操作。

这是一个中间件示例。

 app.Use(async (context, next) => { if (!IsMultipartContentType(context.Request.ContentType)) { await next(); return; } var boundary = GetBoundary(context.Request.ContentType); var reader = new MultipartReader(boundary, context.Request.Body); var section = await reader.ReadNextSectionAsync(); while (section != null) { // process each image const int chunkSize = 1024; var buffer = new byte[chunkSize]; var bytesRead = 0; var fileName = GetFileName(section.ContentDisposition); using (var stream = new FileStream(fileName, FileMode.Append)) { do { bytesRead = await section.Body.ReadAsync(buffer, 0, buffer.Length); stream.Write(buffer, 0, bytesRead); } while (bytesRead > 0); } section = await reader.ReadNextSectionAsync(); } context.Response.WriteAsync("Done."); }); 

这是助手。

 private static bool IsMultipartContentType(string contentType) { return !string.IsNullOrEmpty(contentType) && contentType.IndexOf("multipart/", StringComparison.OrdinalIgnoreCase) >= 0; } private static string GetBoundary(string contentType) { var elements = contentType.Split(' '); var element = elements.Where(entry => entry.StartsWith("boundary=")).First(); var boundary = element.Substring("boundary=".Length); // Remove quotes if (boundary.Length >= 2 && boundary[0] == '"' && boundary[boundary.Length - 1] == '"') { boundary = boundary.Substring(1, boundary.Length - 2); } return boundary; } private string GetFileName(string contentDisposition) { return contentDisposition .Split(';') .SingleOrDefault(part => part.Contains("filename")) .Split('=') .Last() .Trim('"'); } 

外部参考

在您的Controller您只需使用Request.Form.Files来访问文件:

 [HttpPost("upload")] public async Task UploadAsync(CancellationToken cancellationToken) { if (!Request.HasFormContentType) return BadRequest(); var form = Request.Form; foreach(var formFile in form.Files) { using(var readStream = formFile.OpenReadStream()) { // Do something with the uploaded file } } return Ok(); }