zoukankan      html  css  js  c++  java
  • ActionFilterAttribute之HtmlFilter,压缩HTML代码

    当开启这个过滤器后,最终生成的HTML代码将会被压缩一下,在流量很大的网站中,能减少带宽成本就减少一点,何乐而不为?

    [csharp] view plaincopy
    1. using System;  
    2. using System.Collections.Generic;  
    3. using System.Linq;  
    4. using System.Text;  
    5. using System.Text.RegularExpressions;  
    6. using System.Web.Mvc;  
    7. using Mkt.Common;  
    8.   
    9. namespace Mkt.Mvc.Filter  
    10. {  
    11.     public class HtmlFilter : ActionFilterAttribute  
    12.     {  
    13.  
    14.         #region = IsAvailable =  
    15.   
    16.         private bool _isavailable = true;  
    17.   
    18.         public bool IsAvailable  
    19.         {  
    20.             get { return _isavailable; }  
    21.             set { _isavailable = value; }  
    22.         }  
    23.  
    24.         #endregion  
    25.         public HtmlFilter() { }  
    26.         public HtmlFilter(bool isAvailable)  
    27.         {  
    28.             _isavailable = isAvailable;  
    29.         }  
    30.         public string SetGray(string text)  
    31.         {  
    32.             text = Common.HtmlHelper.Compress(text);  
    33.             if (DateTime.Now.Month == 4 && DateTime.Now.Day == 21)  
    34.             {  
    35.                 text = Regex.Replace(text, "</head>", @"<style type=""text/css"">html {filter:gray;}</style></head>  
    36. ", RegexOptions.IgnoreCase);  
    37.             }  
    38.             return text;  
    39.         }  
    40.         public override void OnActionExecuting(ActionExecutingContext filterContext)  
    41.         {  
    42.             base.OnActionExecuting(filterContext);  
    43.         }  
    44.         public override void OnResultExecuted(ResultExecutedContext filterContext)  
    45.         {  
    46.             base.OnResultExecuted(filterContext);  
    47.             if (!IsAvailable) return;  
    48. #if DEBUG  
    49.             return;  
    50. #endif  
    51.             filterContext.RequestContext.HttpContext.Response.Filter = new HtmlStreamFilter(filterContext.RequestContext.HttpContext.Response.Filter, filterContext.RequestContext.HttpContext.Response.ContentEncoding, SetGray);  
    52.         }  
    53.     }  
    54. }  

    compress代码:

    [csharp] view plaincopy
    1. /// <summary>  
    2.         /// 压缩html代码  
    3.         /// </summary>  
    4.         /// <param name="text">The text.</param>  
    5.         /// <returns></returns>  
    6.         public static string Compress(string text)  
    7.         {  
    8.             text = Regex.Replace(text, @"<!--S*?-->", string.Empty);  
    9.             text = Regex.Replace(text, @"^s+|s+{1}quot;, string.Empty);  
    10.             text = Regex.Replace(text, " ", " ");  
    11.             text = Regex.Replace(text, @">s+?<", "><");  
    12.             text = Regex.Replace(text, @"s{2,}", " ");  
    13.             text = Regex.Replace(text, " {2,}", @"s");  
    14.             text = Regex.Replace(text, @"s{2,}", @"s");  
    15.           
    16.             return text;  
    17.         }  


    其中的SetGray是4.21哀悼日变灰设置.

    配合CompressFilter,效果更佳~


    之前露掉了HtmlStreamFilter的源码,如下:

    [csharp] view plaincopy
    1. public class HtmlStreamFilter : Stream  
    2.     {  
    3.         Stream responseStream;  
    4.         long position;  
    5.         StringBuilder responseHtml;  
    6.         #region = CurrentEncoding =  
    7.   
    8.         private Encoding _currentencoding;  
    9.   
    10.         public Encoding CurrentEncoding  
    11.         {  
    12.             get { return _currentencoding; }  
    13.             set { _currentencoding = value; }  
    14.         }  
    15.  
    16.         #endregion  
    17.         Func<string, string> _func;  
    18.         public HtmlStreamFilter(Stream inputStream, Encoding enc, Func<string, string> func  
    19. )  
    20.         {  
    21.             responseStream = inputStream;  
    22.             _currentencoding = enc;  
    23.             _func = func;  
    24.             responseHtml = new StringBuilder();  
    25.         }  
    26.  
    27.         #region Filter overrides  
    28.         public override bool CanRead  
    29.         {  
    30.             get { return true; }  
    31.         }  
    32.   
    33.         public override bool CanSeek  
    34.         {  
    35.             get { return true; }  
    36.         }  
    37.   
    38.         public override bool CanWrite  
    39.         {  
    40.             get { return true; }  
    41.         }  
    42.   
    43.         public override void Close()  
    44.         {  
    45.             responseStream.Close();  
    46.         }  
    47.   
    48.         public override void Flush()  
    49.         {  
    50.             responseStream.Flush();  
    51.         }  
    52.   
    53.         public override long Length  
    54.         {  
    55.             get { return 0; }  
    56.         }  
    57.   
    58.         public override long Position  
    59.         {  
    60.             get { return position; }  
    61.             set { position = value; }  
    62.         }  
    63.   
    64.         public override long Seek(long offset, SeekOrigin origin)  
    65.         {  
    66.             return responseStream.Seek(offset, origin);  
    67.         }  
    68.   
    69.         public override void SetLength(long length)  
    70.         {  
    71.             responseStream.SetLength(length);  
    72.         }  
    73.   
    74.         public override int Read(byte[] buffer, int offset, int count)  
    75.         {  
    76.             return responseStream.Read(buffer, offset, count);  
    77.         }  
    78.         #endregion  
    79.  
    80.         #region Dirty work  
    81.         public override void Write(byte[] buffer, int offset, int count)  
    82.         {  
    83.             string strBuffer = CurrentEncoding.GetString(buffer, offset, count);  
    84.             #region =如果不是HTML文档,不作处理=  
    85.   
    86.             var bof = new Regex("<html", RegexOptions.IgnoreCase);  
    87.             if (!bof.IsMatch(responseHtml.ToString()))  
    88.             {  
    89.                 responseStream.Write(buffer, offset, count);  
    90.                 return;  
    91.             }  
    92.             #endregion  
    93.             // ---------------------------------  
    94.             // Wait for the closing </html> tag  
    95.             // ---------------------------------  
    96.             Regex eof = new Regex("</html>", RegexOptions.IgnoreCase);  
    97.   
    98.             if (!eof.IsMatch(strBuffer))  
    99.             {  
    100.                 responseHtml.Append(strBuffer);  
    101.             }  
    102.             else  
    103.             {  
    104.                 responseHtml.Append(strBuffer);  
    105.                 string finalHtml = responseHtml.ToString();  
    106.   
    107.                 finalHtml = _func(finalHtml);  
    108.   
    109.                 // Transform the response and write it back out  
    110.   
    111.                 byte[] data = CurrentEncoding.GetBytes(finalHtml);  
    112.   
    113.                 responseStream.Write(data, 0, data.Length);  
    114.             }  
    115.         }  
    116.         #endregion  
    117.   
    118.     }  

    第二种方法,使用.net内部类实现:

    [csharp] view plaincopy
    1. public class HtmlFilter : ActionFilterAttribute  
    2.     {  
    3.  
    4.         #region = IsAvailable =  
    5.   
    6.         private bool _isavailable = true;  
    7.   
    8.         public bool IsAvailable  
    9.         {  
    10.             get { return _isavailable; }  
    11.             set { _isavailable = value; }  
    12.         }  
    13.  
    14.         #endregion  
    15.         private TextWriter _originalWriter;  
    16.         private static readonly MethodInfo SwitchWriterMethod = typeof(HttpResponse).GetMethod("SwitchWriter", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);  
    17.         public HtmlFilter() { }  
    18.         public HtmlFilter(bool isAvailable)  
    19.         {  
    20.             _isavailable = isAvailable;  
    21.         }  
    22.         public string SetGray(string text)  
    23.         {  
    24.             text = Common.HtmlHelper.Compress(text);  
    25.             if (DateTime.Now.Month == 4 && DateTime.Now.Day == 21)  
    26.             {  
    27.                 text = Regex.Replace(text, "</head>", @"<style type=""text/css"">html {filter:gray;}</style></head>  
    28. ", RegexOptions.IgnoreCase);  
    29.             }  
    30.             return text;  
    31.         }  
    32.         public override void OnActionExecuting(ActionExecutingContext filterContext)  
    33.         {  
    34.             if (!IsAvailable) return;  
    35. #if DEBUG  
    36.             return;  
    37. #endif  
    38.             _originalWriter = (TextWriter)SwitchWriterMethod.Invoke(HttpContext.Current.Response, new object[] { new HtmlTextWriter(new StringWriter()) });  
    39.             base.OnActionExecuting(filterContext);  
    40.         }  
    41.         public override void OnResultExecuted(ResultExecutedContext filterContext)  
    42.         {  
    43.             base.OnResultExecuted(filterContext);  
    44.             if (!IsAvailable) return;  
    45. #if DEBUG  
    46.             return;  
    47. #endif  
    48.   
    49.             HtmlTextWriter cacheWriter = (HtmlTextWriter)SwitchWriterMethod.Invoke(HttpContext.Current.Response, new object[] { _originalWriter });  
    50.             string textWritten = cacheWriter.InnerWriter.ToString();  
    51.             if (filterContext.HttpContext.Response.ContentType == "text/html")  
    52.             {  
    53.                 textWritten = Compress(textWritten).ToString();  
    54.             }  
    55.             filterContext.HttpContext.Response.Write(textWritten);  
    56.             //filterContext.RequestContext.HttpContext.Response.Filter = new HtmlStreamFilter(filterContext.RequestContext.HttpContext.Response.Filter, filterContext.RequestContext.HttpContext.Response.ContentEncoding, SetGray);  
    57.         }  
    58.         private static StringBuilder Compress(string text)  
    59.         {  
    60.             StringBuilder str = new StringBuilder();  
    61.             StringBuilder strlink = new StringBuilder();  
    62.             var s = new char[] { 'f', ' ', ' ', ' ', 'v' };  
    63.             Func<int, object> P = c => null;  
    64.             Func<int, object> Ptag = c => null; //标签处理机  
    65.             Func<int, object> Pcomment = c => null; //注释  
    66.  
    67.             #region - 总处理机 -  
    68.             Func<int, object> state = P = i =>  
    69.             {  
    70.                 char c = text[i];  
    71.                 if (c == '<') //碰到<交个Ptag处理机  
    72.                 {  
    73.                     if (i + 4 < text.Length)  
    74.                     {  
    75.                         if (text.Substring(i + 1, 3) == "!--") //交个注释处理机  
    76.                         {  
    77.                             return Pcomment;  
    78.                         }  
    79.                     }  
    80.                     str.Append(c);  
    81.                     return Ptag;  
    82.                 }  
    83.                 else if (s.Contains(c) == true) { return P; }  
    84.                 else if (c == ' ')  
    85.                 {  
    86.                     if (i + 1 < text.Length)  
    87.                     {  
    88.                         if (s.Union(new char[] { ' ', '<' }).Contains(text[i + 1]) == false)  
    89.                         {  
    90.                             str.Append(c);  
    91.                         }  
    92.                     }  
    93.                     return P;  
    94.                 }  
    95.                 else  
    96.                 {  
    97.                     str.Append(c);  
    98.                     return P;  
    99.                 }  
    100.             };  
    101.             #endregion  
    102.  
    103.             #region - Tag处理机 -  
    104.             Ptag = i =>  
    105.             {  
    106.                 char c = text[i];  
    107.                 if (c == '>') //交还给p  
    108.                 {  
    109.                     str.Append(c);  
    110.                     return P;  
    111.                 }  
    112.                 else if (s.Contains(c) == true) { return Ptag; }  
    113.                 else if (c == ' ')  
    114.                 {  
    115.                     if (i + 1 < text.Length)  
    116.                     {  
    117.                         if (new char[] { ' ', '/', '=', '>' }.Contains(text[i + 1]) == false)  
    118.                         {  
    119.                             str.Append(c);  
    120.                         }  
    121.                     }  
    122.                     return Ptag;  
    123.                 }  
    124.                 else  
    125.                 {  
    126.                     str.Append(c);  
    127.                     return Ptag;  
    128.                 }  
    129.             };  
    130.             #endregion  
    131.  
    132.             #region - 注释处理机 -  
    133.             Pcomment = i =>  
    134.             {  
    135.                 char c = text[i];  
    136.                 if (c == '>' && text.Substring(i - 2, 3) == "-->")  
    137.                 {  
    138.                     return P;  
    139.                 }  
    140.                 else  
    141.                 {  
    142.                     return Pcomment;  
    143.                 }  
    144.             };  
    145.             #endregion  
    146.   
    147.             for (int index = 0; index < text.Length; index++)  
    148.             {  
    149.                 state = (Func<int, object>)state(index);  
    150.             }  
    151.   
    152.             return str;  
    153.         }  
    154.     }  

    此方法中新的compress方法使用的GoodSpeed的成果.
  • 相关阅读:
    冒泡排序、选择排序、简单二分查找
    asp.net和js读取文件的MD5值的方法
    C#对.CSV格式的文件--逗号分隔值文件 的读写操作及上传ftp服务器操作方法总结
    利用jQueryRotate旋转插件开发大转盘抽奖
    说说第三方支付接口开发及开发中遇到的坑爹问题
    浅谈程序员接私单那点事及接私单需要注意的问题
    C#微信公众号接口开发,灵活利用网页授权、带参数二维码、模板消息,提升用户体验之完成用户绑定个人微信及验证码获取
    C#.NET微信公众账号接口开发系列文章整理--微信接口开发目录,方便需要的博友查询
    C#/ASP.NET MVC微信公众号接口开发之从零开发(四) 微信自定义菜单(附源码)
    C#/ASP.NET MVC微信公众号接口开发之从零开发(三)回复消息 (附源码)
  • 原文地址:https://www.cnblogs.com/waters/p/3844099.html
Copyright © 2011-2022 走看看