zoukankan      html  css  js  c++  java
  • MVC 中对返回的 data 进行压缩

    在webAPI 中返回数据,在数据量比较大的情况的下,返回的data 也可能比较大,有时候可能大于1兆,因此对数据进行压缩能极大的提高数据下载到客户端的时间,提高页面的加载速度。

    思路: 在web api 中添加 action filter attribute 来实现,我们先看下其定义:

     [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
      public abstract class ActionFilterAttribute : FilterAttribute, IActionFilter, IFilter
      {
        /// <summary>
        /// Occurs before the action method is invoked.
        /// </summary>
        /// <param name="actionContext">The action context.</param>
        public virtual void OnActionExecuting(HttpActionContext actionContext);
        /// <summary>
        /// Occurs after the action method is invoked.
        /// </summary>
        /// <param name="actionExecutedContext">The action executed context.</param>
        public virtual void OnActionExecuted(HttpActionExecutedContext actionExecutedContext);
        /// <summary>
        /// Executes the filter action asynchronously.
        /// </summary>
        /// 
        /// <returns>
        /// The newly created task for this operation.
        /// </returns>
        /// <param name="actionContext">The action context.</param><param name="cancellationToken">The cancellation token assigned for this task.</param><param name="continuation">The delegate function to continue after the action method is invoked.</param>
        Task<HttpResponseMessage> IActionFilter.ExecuteActionFilterAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation);
      }

    代码很清晰,关键是两个虚方法 OnActionExecuting(在controller 调用 action方法之前执行),OnActionExecuted( 在controller 调用 action方法之后执行)。

    因为我们要对action 执行后的json 进行压缩,所以我们只需要重写OnActionExecuted 方法即可。

    在工程中添加一个类CompressResponseAttribute.cs,

    具体实现代码如下:

        public class CompressResponseAttribute : ActionFilterAttribute
        {
            public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
            {
                var request = actionExecutedContext.Request;
                var response = actionExecutedContext.Response;
    
                var contentBytes = response.Content.ReadAsByteArrayAsync().Result;
                byte[] compressedBytes;
                string contentEncoding = string.Empty;
    
                using (var output = new MemoryStream())
                {
                    if (request.Headers.AcceptEncoding.Any(v => v.Value.Equals("gzip", StringComparison.OrdinalIgnoreCase)))
                    {
                        contentEncoding = "gzip";
                        using (var gZipStream = new GZipStream(output, CompressionMode.Compress))
                        {
                            gZipStream.Write(contentBytes, 0, contentBytes.Length);
                        }
                    }
                    else if (request.Headers.AcceptEncoding.Any(v => v.Value.Equals("deflate", StringComparison.OrdinalIgnoreCase)))
                    {
                        contentEncoding = "deflate";
                        using (var deflateStream = new DeflateStream(output, CompressionMode.Compress))
                        {
                            deflateStream.Write(contentBytes, 0, contentBytes.Length);
                        }
                    }
                    compressedBytes = output.ToArray();
                }
                        
    
                if (!string.IsNullOrEmpty(contentEncoding))
                {
                    var originalContentType = response.Content.Headers.ContentType.ToString();
    
                    response.Content = new System.Net.Http.ByteArrayContent(compressedBytes);
                    response.Content.Headers.Remove("Content-Type");
                    response.Content.Headers.Add("Content-encoding", contentEncoding);
                    response.Content.Headers.Add("Content-Type", originalContentType);
                }
    
                base.OnActionExecuted(actionExecutedContext);
            }
        }

    上面的代码实现的压缩方式优先为gzip。

    最后,在需要压缩返回的method 上面添加 [CompressResponse] 标注  即可。

  • 相关阅读:
    startActivityForResult()的用法(转)
    计算机的特点
    Pinyin4j的基本用法
    简述Asp.net中断点续传的原理与实现
    ACE自适配通信环境简介
    如何将sql查询结果(不止一项)插入到一张表中
    CShell简介
    解析自定义时间格式字符串
    彻底删除IE核心浏览器的右键菜单残留项
    ACE线程管理机制
  • 原文地址:https://www.cnblogs.com/slardar1978/p/4203325.html
Copyright © 2011-2022 走看看