HTTP压缩

一、问题描述

有一页面打开需要11s左右,通过谷歌DevTools工具可以看看到,服务器接口的响应是很快的(TTFB也就200ms),但是前端接收数据的时间有点长(Content Download达到了11s)。经过查看后发现接口返回的数据量达到了12M,数据量比较大。

二、解决方案

1、优化代码,前端不需要的数据,接口不再返回。

2、压缩接口返回的数据

三、压缩接口返回的数据

我们需要在调用操作方法之后执行压缩,所以自定义一个特性,重写ActionFilterAttribute中的OnActionExecuted方法。

using System;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net.Http;
using System.Web.Http.Filters;

namespace Common.WebApi.Attributes
{
    /// <summary>
    /// 数据压缩
    /// </summary>
    public class DataZipAttribute : ActionFilterAttribute
    {/// <summary>
        /// 压缩数据
        /// </summary>
        /// <param name="actionExecutedContext"></param>
        public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
        {
            try
            {
                DataGzip(actionExecutedContext);
            }
            catch (Exception ex)
            {
                //日志记录
            }

        }       
        /// <summary>
        /// 数据压缩
        /// </summary>
        /// <param name="actionExecutedContext"></param>
        private void DataGzip(HttpActionExecutedContext actionExecutedContext)
        {
            var content = actionExecutedContext.Response.Content;
            var acceptEncoding = actionExecutedContext.Request.Headers.AcceptEncoding.Where(x => x.Value == "gzip" || x.Value == "deflate").ToList();
            if (acceptEncoding != null && acceptEncoding.Count > 0 && content != null && actionExecutedContext.Request.Method != HttpMethod.Options)
            {
                var bytes = content.ReadAsByteArrayAsync().Result;
                if (acceptEncoding.FirstOrDefault().Value == "gzip")
                {
                    actionExecutedContext.Response.Content = new ByteArrayContent(CompressionHelper.GzipCompress(bytes));
                    actionExecutedContext.Response.Content.Headers.Add("Content-Encoding", "gzip");
                }
                else if (acceptEncoding.FirstOrDefault().Value == "deflate")
                {
                    actionExecutedContext.Response.Content = new ByteArrayContent(CompressionHelper.DeflateCompress(bytes));
                    actionExecutedContext.Response.Content.Headers.Add("Content-encoding", "deflate");
                }
            }
        } 
    }
public class CompressionHelper { public static byte[] DeflateCompress(byte[] data) { if (data == null || data.Length < 1) return data; try { using (MemoryStream stream = new MemoryStream()) { using (DeflateStream gZipStream = new DeflateStream(stream, CompressionMode.Compress)) { gZipStream.Write(data, 0, data.Length); gZipStream.Close(); } return stream.ToArray(); } } catch (Exception) { return data; } } public static byte[] GzipCompress(byte[] data) { if (data == null || data.Length < 1) return data; try { using (MemoryStream stream = new MemoryStream()) { using (GZipStream gZipStream = new GZipStream(stream, CompressionMode.Compress)) { gZipStream.Write(data, 0, data.Length); gZipStream.Close(); } return stream.ToArray(); } } catch (Exception) { return data; } } } }

在controller文件中引用

[DataZipAttribute ]
public class XXXController : ApiController
{           
}

或者在action方法上引用

[HttpPost]
[DataZipAttribute]
public HttpResponseMessage Get()
{

}

或者全局引用,在Global文件中

protected void Application_Start()
{            
  GlobalConfiguration.Configuration.Filters.Add(new DataZipAttribute());//数据压缩
}

四、HTTP压缩

HTTP压缩是指在Web服务器和浏览器间传输压缩文本内容的方法。HTTP压缩通常采用gzip或者deflate压缩算法压缩HTML、JavaScript、CSS等文件。压缩的最大好处就是降低了网络传输的数据量,从而提高客户端浏览器的访问速度。当然,同时也会增加一点服务器的负担。

1、简述

通过开启服务器端的HTTP压缩功能,也可以提高网站的浏览速度,对优化文件的传输也不失为一种好的方法。只是该方法会提高服务器CPU的负荷。如果服务器CPU本身负荷就大,就需要好好地斟酌了。HTTP压缩的原理是服务器接收到客户端的HTTP请求后,检查浏览器是否支持HTTP压缩,如果支持,则根据配置压缩相应的网页文件,压缩文件下载到客户端后,由浏览器解压文件后再浏览。HTTP压缩的比较通用的算法是GZIP、deflate,所以开启服务端的HTTP压缩功能一般是指开启服务器端的GZIP功能。

2、原理

Web服务器处理HTTP压缩的工作原理如下:
(1)Web服务器接收到浏览器的HTTP请求后,检查浏览器是否支持HTTP压缩;在用户浏览器发送请求的HTTP头中,带有" Accept-Encoding:gzip,deflate"参数则表明支持gzip和 deflate两种压缩算法。
var acceptEncoding = actionExecutedContext.Request.Headers.AcceptEncoding.Where(x => x.Value == "gzip" || x.Value == "deflate").ToList();            

(2)服务器收到浏览器发送的请求之后,判断浏览器是否支持gzip,如果支持gzip,则使用gzip算法进行压缩;如果支持deflate,则使用deflate算法进行压缩。如果都不支持,则向浏览器发送未经压缩的内容。

if (acceptEncoding.FirstOrDefault().Value == "gzip")
{
  actionExecutedContext.Response.Content = new ByteArrayContent(CompressionHelper.GzipCompress(bytes));
  actionExecutedContext.Response.Content.Headers.Add("Content-Encoding", "gzip");
}
else if (acceptEncoding.FirstOrDefault().Value == "deflate")
{
  actionExecutedContext.Response.Content
= new ByteArrayContent(CompressionHelper.DeflateCompress(bytes));   actionExecutedContext.Response.Content.Headers.Add("Content-encoding", "deflate"); }

(3)浏览器接收到服务器的响应之后判断内容是否被压缩,如果被压缩则解压缩显示页面内容。

3、总结

目前大多数浏览器是支持gzip和deflate压缩的,我们可以通过浏览器请求头的accept-encoding看看浏览器支持的压缩方案

HTTP压缩

五、gzip和deflate概述

 

六、服务端开启Gzip压缩方式

 

七、检测压缩的效率

 

HTTP压缩

上一篇:NSString相关操作


下一篇:iOS - Json解析精度丢失处理(NSString, Double, Float)