利用现成的轮子,下载程序包【DotNetZip】即可,此时我们则需要在执行方法完毕后来进行内容的压缩即可,所以我们需要重写【 ActionFilterAttribute 】过滤器,在此基础上进行我们的压缩操作。如下:
public class DeflateCompressionAttribute : ActionFilterAttribute { OnActionExecuted(HttpActionExecutedContext actionContext) { var content = actionContext.Response.Content; var bytes = content == null ? null : content.ReadAsByteArrayAsync().Result; var compressContent = bytes == null ? new byte[0] : CompressionHelper.DeflateByte(bytes); actionContext.Response.Content = new ByteArrayContent(compressContent); actionContext.Response.Content.Headers.Remove(); )) actionContext.Response.Content.Headers.Add(, ); else actionContext.Response.Content.Headers.Add(, ); actionContext.Response.Content.Headers.Add(, ); base.OnActionExecuted(actionContext); } }
利用DotNetZip进行快速压缩:
public class CompressionHelper { [] DeflateByte(byte[] str) { if (str == null) { return null; } using (var output = new MemoryStream()) { using (var compressor = new Ionic.Zlib.GZipStream( output, Ionic.Zlib.CompressionMode.Compress, Ionic.Zlib.CompressionLevel.BestSpeed)) { compressor.Write(str, 0, str.Length); } return output.ToArray(); } } }
我们来对比看一下未进行内容压缩前后结果响应的时间以及内容长度,给出如下测试类:
[HttpGet] [DeflateCompression] public async Task<IHttpActionResult> GetZipData() { Dictionary<object, object> dict = new Dictionary<object, object>(); List<Employee> li = new List<Employee>(); li.Add(, Name = , Email = }); li.Add(, Name = , Email = }); li.Add(, Name = , Email = }); li.Add(, Name = ,Email = }); dict.Add( Ok(dict); }
结果运行错误:
这里应该是序列化出现问题,在有些浏览器返回的XML数据,我用的是搜狗浏览器,之前学习WebAPi时其返回的就是XML数据,我们试着将其返回为Json数据看看。
var formatters = config.Formatters.Where(formatter => formatter.SupportedMediaTypes.Where(media => media.MediaType.ToString() == || media.MediaType.ToString() == ).Count() > 0) //找到请求头信息中的介质类型 .ToList(); foreach (var match in formatters) { config.Formatters.Remove(match); }
我们未将其压缩后响应的长度如下所示:
压缩后结果明显得到提升
接下来我们自定义用.NET内置的压缩模式来实现看看
压缩方式(3)既然响应的内容是通过HttpContent,我们则需要在重写过滤器ActionFilterAttribute的基础上来实现重写HttpContent,最终根据获取到浏览器支持的压缩格式对数据进行压缩并写入到响应流中即可。