加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > asp.Net > 正文

如何使用ASP.NET Core创建多部分HTTP响应

发布时间:2020-12-15 20:09:29 所属栏目:asp.Net 来源:网络整理
导读:我想在我的ASP.NET核心控制器中创建一个操作方法,它返回一个包含多个文件的Multipart HTTP响应.我知道使用.zip文件是网站的推荐方法,但我正在考虑使用这样的API请求. 在ASP.NET Core示例中可以使用find的示例在上传文件时需要使用多部分HTTP请求.在我的情况
我想在我的ASP.NET核心控制器中创建一个操作方法,它返回一个包含多个文件的Multipart HTTP响应.我知道使用.zip文件是网站的推荐方法,但我正在考虑使用这样的API请求.

在ASP.NET Core示例中可以使用find的示例在上传文件时需要使用多部分HTTP请求.在我的情况下,我想下载文件.

UPDATE

我提出了以下GitHub问题:#4933

解决方法

从MSDN

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还提供了这个技术定义:

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:   none

RFC的最好的部分是其示例,下面的ASP.NET Core示例说明了这一点.

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.

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 = "rn";
    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);
    }
}

注意:此示例代码在进行生产之前需要重构.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读