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

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

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

private void OnWrite() { if (!_compressionChecked) { _compressionChecked = true; //判断是否满足执行压缩相关的逻辑 if (_provider.ShouldCompressResponse(_context)) { //匹配Vary头信息对应的值 var varyValues = _context.Response.Headers.GetCommaSeparatedValues(HeaderNames.Vary); var varyByAcceptEncoding = false; //判断Vary的值是否为Accept-Encoding for (var i = 0; i < varyValues.Length; i++) { if (string.Equals(varyValues[i], HeaderNames.AcceptEncoding, StringComparison.OrdinalIgnoreCase)) { varyByAcceptEncoding = true; break; } } if (!varyByAcceptEncoding) { _context.Response.Headers.Append(HeaderNames.Vary, HeaderNames.AcceptEncoding); } //获取最佳的ICompressionProvider即最佳的压缩方式 var compressionProvider = ResolveCompressionProvider(); if (compressionProvider != null) { //设置选定的压缩算法,放入Content-Encoding头的值里 //客户端可以通过Content-Encoding头信息判断服务端采用的哪种压缩算法 _context.Response.Headers.Append(HeaderNames.ContentEncoding, compressionProvider.EncodingName); //进行压缩时,将 Content-MD5 删除该标头,因为正文内容已更改且哈希不再有效。 _context.Response.Headers.Remove(HeaderNames.ContentMD5); //进行压缩时,将 Content-Length 删除该标头,因为在对响应进行压缩时,正文内容会发生更改。 _context.Response.Headers.Remove(HeaderNames.ContentLength); //返回压缩相关输出流 _compressionStream = compressionProvider.CreateStream(_innerStream); } } } } private ICompressionProvider ResolveCompressionProvider() { if (!_providerCreated) { _providerCreated = true; //调用ResponseCompressionProvider的方法返回最合适的压缩算法 _compressionProvider = _provider.GetCompressionProvider(_context); } return _compressionProvider; }

从上面的逻辑我们可以看到,在执行压缩相关逻辑之前需要判断是否满足执行压缩相关的方法ShouldCompressResponse,这个方法是ResponseCompressionProvider里的方法,这里就不再粘贴代码了,本来就是判断逻辑我直接整理出来大致就是一下几种情况

如果请求是Https的情况下,是否设置了允许Https情况下压缩的设置,即ResponseCompressionOptions的EnableForHttps属性设置

Response.Head里不能包含Content-Range头信息

Response.Head里之前不能包含Content-Encoding头信息

Response.Head里之前必须要包含Content-Type头信息

返回的MimeType里不能包含配置的不需要压缩的类型,即ResponseCompressionOptions的ExcludedMimeTypes

返回的MimeType里需要包含配置的需要压缩的类型,即ResponseCompressionOptions的MimeTypes

如果不满足上面的两种情况,返回的MimeType里包含*/*也可以执行响应压缩

接下来我们查看ResponseCompressionProvider的GetCompressionProvider方法看它是如何确定返回哪一种压缩类型的

public virtual ICompressionProvider GetCompressionProvider(HttpContext context) { var accept = context.Request.Headers[HeaderNames.AcceptEncoding]; //判断请求头是否包含Accept-Encoding信心 if (StringValues.IsNullOrEmpty(accept)) { Debug.Assert(false, "Duplicate check failed."); return null; } //获取Accept-Encoding里的值,判断是否包含gzip、br、identity等,并返回匹配信息 if (!StringWithQualityHeaderValue.TryParseList(accept, out var encodings) || !encodings.Any()) { return null; } //根据请求信息和设置信息计算匹配优先级 var candidates = new HashSet<ProviderCandidate>(); foreach (var encoding in encodings) { var encodingName = encoding.Value; //Quality涉及到一个非常复杂的算法,有兴趣的可以自行查阅 var quality = encoding.Quality.GetValueOrDefault(1); //quality需大于0 if (quality < double.Epsilon) { continue; } //匹配请求头里encodingName和设置的providers压缩算法里EncodingName一致的算法 //从这里可以看出匹配的优先级和注册providers里的顺序也有关系 for (int i = 0; i < _providers.Length; i++) { var provider = _providers[i]; if (StringSegment.Equals(provider.EncodingName, encodingName, StringComparison.OrdinalIgnoreCase)) { candidates.Add(new ProviderCandidate(provider.EncodingName, quality, i, provider)); } } //如果请求头里EncodingName是*的情况则在所有注册的providers里进行匹配 if (StringSegment.Equals("*", encodingName, StringComparison.Ordinal)) { for (int i = 0; i < _providers.Length; i++) { var provider = _providers[i]; candidates.Add(new ProviderCandidate(provider.EncodingName, quality, i, provider)); } break; } //如果请求头里EncodingName是identity的情况,则不对响应进行编码 if (StringSegment.Equals("identity", encodingName, StringComparison.OrdinalIgnoreCase)) { candidates.Add(new ProviderCandidate(encodingName.Value, quality, priority: int.MaxValue, provider: null)); } } ICompressionProvider selectedProvider = null; //如果匹配的只有一个则直接返回 if (candidates.Count <= 1) { selectedProvider = candidates.FirstOrDefault().Provider; } else { //如果匹配到多个则按照Quality倒序和Priority正序的负责匹配第一个 selectedProvider = candidates .OrderByDescending(x => x.Quality) .ThenBy(x => x.Priority) .First().Provider; } //如果没有匹配到selectedProvider或是identity的情况直接返回null if (selectedProvider == null) { return null; } return selectedProvider; }

通过以上的介绍我们可以大致了解到响应压缩的大致工作方式,简单总结一下

首先设置压缩相关的算法类型或是压缩目标的MimeType

其次我们可以设置压缩级别,这将决定压缩的质量和压缩性能

(编辑:晋中站长网)

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

热点阅读