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

ASP.NET Core中的响应压缩的实现

发布时间:2020-08-21 13:39:32 所属栏目:编程 来源:网络整理
导读:这篇文章主要介绍了ASP.NET Core中的响应压缩的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编

public class GzipCompressionProvider : ICompressionProvider { public GzipCompressionProvider(IOptions<GzipCompressionProviderOptions> options) { Options = options.Value; } private GzipCompressionProviderOptions Options { get; } // 对应的Encoding名称 public string EncodingName { get; } = "gzip"; public bool SupportsFlush => true; // 核心代码就是这句 将原始的输出流转换为压缩的GZipStream // 我们设置的Level压缩级别将决定压缩的性能和质量 public Stream CreateStream(Stream outputStream) => new GZipStream(outputStream, Options.Level, leaveOpen: true); }

关于ResponseCompressionProvider其他相关的方法咱们在讲解UseResponseCompression中间件的时候在具体看用到的方法,因为这个类是响应压缩的核心类,现在提前说了,到中间件使用的地方可能会忘记了。接下来我们就看UseResponseCompression的大致实现。

UseResponseCompression#

UseResponseCompression具体也就一个无参的扩展方法,也比较简单,因为配置和工作都由注入的地方完成了,所以我们直接查看中间件里的实现,找到中间件位置ResponseCompressionMiddleware[点击查看源码👈]

public class ResponseCompressionMiddleware { private readonly RequestDelegate _next; private readonly IResponseCompressionProvider _provider; public ResponseCompressionMiddleware(RequestDelegate next, IResponseCompressionProvider provider) { _next = next; _provider = provider; } public async Task Invoke(HttpContext context) { //判断是否包含Accept-Encoding头信息,不包含直接大喊一声"抬走下一个" if (!_provider.CheckRequestAcceptsCompression(context)) { await _next(context); return; } //获取原始输出Body var originalBodyFeature = context.Features.Get<IHttpResponseBodyFeature>(); var originalCompressionFeature = context.Features.Get<IHttpsCompressionFeature>(); //初始化响应压缩Body var compressionBody = new ResponseCompressionBody(context, _provider, originalBodyFeature); //设置成压缩Body context.Features.Set<IHttpResponseBodyFeature>(compressionBody); context.Features.Set<IHttpsCompressionFeature>(compressionBody); try { await _next(context); await compressionBody.FinishCompressionAsync(); } finally { //恢复原始Body context.Features.Set(originalBodyFeature); context.Features.Set(originalCompressionFeature); } } }

这个中间件非常的简单,就是初始化了ResponseCompressionBody。看到这里你也许会好奇,并没有触发调用压缩相关的任何代码,ResponseCompressionBody也只是调用了FinishCompressionAsync都是和释放相关的,不要着急我们来看ResponseCompressionBody类的结构

internal class ResponseCompressionBody : Stream, IHttpResponseBodyFeature, IHttpsCompressionFeature { }

这个类实现了IHttpResponseBodyFeature,我们使用的Response.Body其实就是获取的HttpResponseBodyFeature.Stream属性。我们使用的Response.WriteAsync相关的方法,其实内部都是在调用PipeWriter进行写操作,而PipeWriter就是来自HttpResponseBodyFeature.Writer属性。可以大致概括为,输出相关的操作其核心都是在操作IHttpResponseBodyFeature。有兴趣的可以自行查阅HttpResponse相关的源码可以了解相关信息。所以我们的ResponseCompressionBody其实是重写了输出操作相关方法。也就是说,只要你调用了Response相关的Write或Body相关的,其实本质都是在操作IHttpResponseBodyFeature,由于我们开启了响应输出相关的中间件,所以会调用IHttpResponseBodyFeature的实现类ResponseCompressionBody相关的方法完成输出。和我们常规理解的还是有偏差的,一般情况下我们认为,其实只要针对输出的Stream做操作就可以了,但是响应压缩中间件竟然重写了输出相关的操作。

(编辑:核心网)

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

热点阅读