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] 标注  即可。

  • 相关阅读:
    vs编译在win xp电脑上运行的win32程序遇到的问题记录(无法定位程序输入点GetTickCount64于动态链接库KERNEL32.dll)
    (转载)用VS2012或VS2013在win7下编写的程序在XP下运行就出现“不是有效的win32应用程序“
    记录编译方面的问题(重定义)
    记录一个问题:win32程序release版本和debug版本运行效果不同
    C++复制、压缩文件夹
    foreach 和 list.foreach 初步测试
    转载字典地址:http://blog.csdn.net/aladdinty/article/details/3591789
    WindowsApi 解压缩文件
    23种简洁好看的扁平化模板
    Session为null 问题
  • 原文地址:https://www.cnblogs.com/slardar1978/p/4203325.html
Copyright © 2011-2022 走看看