ASP.NET MVC 网站优化之压缩技术

压缩 html 可以去除代码中无用的空格等,这样可提高网站的加载速度并节省带宽。

实现 ActionFilter 来完成 html 的压缩

public class WhitespaceFilterAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var request = filterContext.HttpContext.Request;
        var response = filterContext.HttpContext.Response;
        response.Filter = new WhiteSpaceFilter(response.Filter, s =>
        {
            s = Regex.Replace(s, @"\s+(?=<)|\s+$|(?<=>)\s+", "");

            //single-line doctype must be preserved
            var firstEndBracketPosition = s.IndexOf(">");
            if (firstEndBracketPosition >= 0)
            {
                s = s.Remove(firstEndBracketPosition, 1);
                s = s.Insert(firstEndBracketPosition, ">");
            }
            return s;
        });
    }
}


使用时在 Action 方法上添加 Filter 属性即可,如下:

[WhitespaceFilter]
public ActionResult Index(string id)
{
    return View();
}

 


我主要修改了下作者使用的正则,因为原正则会将<pre></pre>中的空格也进行替换,并指定编码为 UTF-8。

 

使用 Gzip 压缩
 

  /// <summary>
    ///  gzip
    /// [Compress]
    ///public ActionResult Index(string id)
    ///{
    ///    return View();
    ///}
    /// </summary>
    public class CompressAttribute : ActionFilterAttribute
    {
       public override void OnResultExecuted(ResultExecutedContext filterContext)
        {
            var acceptEncoding = filterContext.HttpContext.Request.Headers["Accept-Encoding"];
            if (!string.IsNullOrEmpty(acceptEncoding))
            {
                acceptEncoding = acceptEncoding.ToLower();
                var response = filterContext.HttpContext.Response;
                if (acceptEncoding.Contains("gzip"))
                {
                    response.AppendHeader("Content-encoding", "gzip");
                    response.Filter = new GZipStream(response.Filter, CompressionMode.Compress);
                }
                else if (acceptEncoding.Contains("deflate"))
                {
                    response.AppendHeader("Content-encoding", "deflate");
                    response.Filter = new DeflateStream(response.Filter, CompressionMode.Compress);
                }
            }
        }
    }




    /// <summary>
    /// 压缩 HTML
    /// [WhitespaceFilter]
    ///public ActionResult Index(string id)
    ///{
    ///    return View();
    ///}
    /// </summary>
    public class WhitespaceFilterAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            var request = filterContext.HttpContext.Request;
            var response = filterContext.HttpContext.Response;
            response.Filter = new WhiteSpaceFilter(response.Filter, s =>
            {
                s = Regex.Replace(s, @"\s+(?=<)|\s+$|(?<=>)\s+", "");


                //single-line doctype must be preserved
                var firstEndBracketPosition = s.IndexOf(">");
                if (firstEndBracketPosition >= 0)
                {
                    s = s.Remove(firstEndBracketPosition, 1);
                    s = s.Insert(firstEndBracketPosition, ">");
                }
                return s;
            });
        }
    }




    public class WhiteSpaceFilter : Stream
    {
        private Stream _shrink;
        private Func<string, string> _filter;


        public WhiteSpaceFilter(Stream shrink, Func<string, string> filter)
        {
            _shrink = shrink;
            _filter = filter;
        }




        public override bool CanRead { get { return true; } }
        public override bool CanSeek { get { return true; } }
        public override bool CanWrite { get { return true; } }
        public override void Flush() { _shrink.Flush(); }
        public override long Length { get { return 0; } }
        public override long Position { get; set; }
        public override int Read(byte[] buffer, int offset, int count)
        {
            return _shrink.Read(buffer, offset, count);
        }
        public override long Seek(long offset, SeekOrigin origin)
        {
            return _shrink.Seek(offset, origin);
        }
        public override void SetLength(long value)
        {
            _shrink.SetLength(value);
        }
        public override void Close()
        {
            _shrink.Close();
        }


        public override void Write(byte[] buffer, int offset, int count)
        {
            // capture the data and convert to string
            byte[] data = new byte[count];
            Buffer.BlockCopy(buffer, offset, data, 0, count);
            string s = Encoding.UTF8.GetString(buffer);


            // filter the string
            s = _filter(s);


            // write the data to stream
            byte[] outdata = Encoding.UTF8.GetBytes(s);
            _shrink.Write(outdata, 0, outdata.GetLength(0));
        }
    }

 

这样当这个Action发生请求的时候返回到客户端的数据页面就会有明显的压缩效果了。

那么如果在我们的程序中每个Action都需要进行压缩处理的话,每个Action都要这样加,感觉很麻烦。所以这里我们可以这样来处理

    [Compress]
    public class BaseController : Controller
    {

    }

定义一个基类Controller,然后之后的所有控制器都进行继承,那么基类Controller的属性也会继承。

public class HomeController : BaseController

    {
        public ActionResult Index()
        {
            ViewBag.Message = "Welcome to ASP.NET MVC!";

            return View();
        }

        public ActionResult About()
        {
            return View();
        }
    }

 

posted @ 2017-09-15 10:53  三人成虎  阅读(1040)  评论(0编辑  收藏  举报