在ASP.NET Core示例中可以使用find的示例在上传文件时需要使用多部分HTTP请求.在我的情况下,我想下载文件.
UPDATE
我提出了以下GitHub问题:#4933
解决方法
MSDN has a document that lists a lot of the multipart subtypes.多部分/ byteranges似乎最适合在HTTP响应中发送多个文件以供客户端应用程序下载.大胆的部分特别相关.
The multipart/byteranges content type is defined as a part of the HTTP message protocol. It includes two or more parts,each with its own Content-Type and Content-Range fields. The parts are separated using a MIME boundary parameter. It allows for binary as well as 7-bit and 8-bit files to be sent as multiple parts with the lengths of the parts being specified in the header of each part. Note that while HTTP makes provisions for using MIME for HTTP documents,HTTP is not strictly MIME-compliant. (Emphasis added.)
来自RFC2068
RFC2068,第19.2节提供了对multipart / byteranges的描述.大胆的部分也是相关的.每个byterange都可以有自己的Content-type,事实证明也可以有自己的Content-disposition.
The multipart/byteranges media type includes two or more parts,each with its own Content-Type and Content-Range fields. The parts are separated using a MIME boundary parameter. (Emphasis added.)
RFC还提供了这个技术定义:
@H_403_34@Media Type name: multipart Media subtype name: byteranges required parameters: boundary Optional parameters: none Encoding considerations: only "7bit","8bit",or "binary" are permitted Security considerations: noneRFC的最好的部分是其示例,下面的ASP.NET Core示例说明了这一点.
@H_403_34@HTTP/1.1 206 Partial content Date: Wed,15 Nov 1995 06:25:24 GMT Last-modified: Wed,15 Nov 1995 04:58:08 GMT Content-type: multipart/byteranges; boundary=THIS_STRING_SEPARATES --THIS_STRING_SEPARATES Content-type: application/pdf Content-range: bytes 500-999/8000 ...the first range... --THIS_STRING_SEPARATES Content-type: application/pdf Content-range: bytes 7000-7999/8000 ...the second range --THIS_STRING_SEPARATES--请注意,它们正在发送两个PDF!这就是你需要的.
一个ASP.NET核心方法
这是一个适用于Firefox的代码示例.也就是说,Firefox下载三个图像文件,我们可以使用Paint打开. The source is on GitHub.
该示例使用app.Run().要使样本适应控制器操作,请将IHttpContextAccessor注入到控制器中,并在操作方法中写入_httpContextAccessor.HttpContext.Response.
@H_403_34@using System.IO; using System.Threading.Tasks; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.DependencyInjection; public class Startup { private const string CrLf = "\r\n"; private const string Boundary = "--THIS_STRING_SEPARATES"; public void ConfigureServices(IServiceCollection services) { services.AddMvc(); } public void Configure(IApplicationBuilder app) { app.Run(async context => { var response = context.Response; response.ContentType = $"multipart/byteranges; boundary={Boundary}"; // TODO Softcode the 'Content-length' header. response.ContentLength = 13646; var contentLength = response.ContentLength.Value; await response.WriteAsync(Boundary + CrLf); var blue = new FileInfo("./blue.jpg"); var red = new FileInfo("./red.jpg"); var green = new FileInfo("./green.jpg"); long start = 0; long end = blue.Length; await AddImage(response,blue,start,end,contentLength); start = end + 1; end = start + red.Length; await AddImage(response,red,contentLength); start = end + 1; end = start + green.Length; await AddImage(response,green,contentLength); response.Body.Flush(); }); } private async Task AddImage(HttpResponse response,FileInfo fileInfo,long start,long end,long total) { var bytes = File.ReadAllBytes(fileInfo.FullName); var file = new FileContentResult(bytes,"image/jpg"); await response .WriteAsync($"Content-type: {file.ContentType.ToString()}" + CrLf); await response .WriteAsync($"Content-disposition: attachment; filename={fileInfo.Name}" + CrLf); await response .WriteAsync($"Content-range: bytes {start}-{end}/{total}" + CrLf); await response.WriteAsync(CrLf); await response.Body.WriteAsync( file.FileContents,offset: 0,count: file.FileContents.Length); await response.WriteAsync(CrLf); await response.WriteAsync(Boundary + CrLf); } }注意:此示例代码在进行生产之前需要重构.