当开启这个过滤器后,最终生成的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. namespace Mkt.Mvc.Filter
  9. {
  10. public class HtmlFilter : ActionFilterAttribute
  11. {
  12. #region = IsAvailable =
  13. private bool _isavailable = true;
  14. public bool IsAvailable
  15. {
  16. get { return _isavailable; }
  17. set { _isavailable = value; }
  18. }
  19. #endregion
  20. public HtmlFilter() { }
  21. public HtmlFilter(bool isAvailable)
  22. {
  23. _isavailable = isAvailable;
  24. }
  25. public string SetGray(string text)
  26. {
  27. text = Common.HtmlHelper.Compress(text);
  28. if (DateTime.Now.Month == 4 && DateTime.Now.Day == 21)
  29. {
  30. text = Regex.Replace(text, "</head>", @"<style type=""text/css"">html {filter:gray;}</style></head>
  31. ", RegexOptions.IgnoreCase);
  32. }
  33. return text;
  34. }
  35. public override void OnActionExecuting(ActionExecutingContext filterContext)
  36. {
  37. base.OnActionExecuting(filterContext);
  38. }
  39. public override void OnResultExecuted(ResultExecutedContext filterContext)
  40. {
  41. base.OnResultExecuted(filterContext);
  42. if (!IsAvailable) return;
  43. #if DEBUG
  44. return;
  45. #endif
  46. filterContext.RequestContext.HttpContext.Response.Filter = new HtmlStreamFilter(filterContext.RequestContext.HttpContext.Response.Filter, filterContext.RequestContext.HttpContext.Response.ContentEncoding, SetGray);
  47. }
  48. }
  49. }

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, "\n", " ");
  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. return text;
  16. }

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

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

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

此方法中新的compress方法使用的GoodSpeed的成果.

ActionFilterAttribute之HtmlFilter,压缩HTML代码的更多相关文章

  1. js数组特定位置元素置空,非null和undefined,实现echarts现状图效果;谷歌格式化压缩js代码

    一.想要实现eCharts线状图表的断点效果,如图(后来又查到数据格式为data:['-', 2, 3,'-' , 5, 6, 7]:也可以断点显示) 这种效果,在设置数据的时候应该是这样: data ...

  2. Linux oracle数据库自动备份自动压缩脚本代码

    Linux oracle数据库备份完成后可以自动压缩脚本代码. 复制代码代码如下: #!/bin/bash #backup.sh #edit: www.jbxue.com ##系统名称 sysname ...

  3. javascript 压缩空格代码演示

          压缩空格代码演示 主要是讲解 压缩一个字符串两段空格          例如:javascript函数里的空格不论是这样     var s = "Hello World     ...

  4. js、css动态压缩页面代码

    1.js.css动态压缩页面代码 <%@ Page Language="C#" AutoEventWireup="true" CodeFile=" ...

  5. nodejs+gulpjs压缩js代码

    1.安装node.js 下载地址:nodejs.org  或者  nodejs.cn 2.安装gulp之前我们需要安装nodejs的环境,检测能够正常使用npm后,我们用npm对gulp进行一次全局安 ...

  6. Joomla - 优化(时区、google字体、压缩图片、压缩自定义代码)

    Joomla - 优化(时区.google字体.压缩图片.压缩自定义代码) 一.时区 发布文章是往往会发现发布时间和当前时间对不上,原因是 Joomla 用的是国际标准时间,和中国时区大约相差8小时, ...

  7. 使用Google Closure Compiler高级压缩Javascript代码注意的几个地方

    介绍 GCC(Google Closure Compiler)是由谷歌发布的Js代码压缩编译工具.它可以做到分析Js的代码,移除不需要的代码(dead code),并且去重写它,最后再进行压缩. 三种 ...

  8. Source Map调试压缩后代码

    在前端开发过程中,无论是样式还是脚本,运行时的文件可能是压缩后的,那这个时候调试起来就很麻烦. 这个时候,可以使用Source Map文件来优化调试,Source Map是一个信息文件,里面储存着原代 ...

  9. 打包并压缩seajs代码

    背景 seajs是一款优秀的模块开发插件,但是当我们使用它来进行模块化开发的时候,由于它的每个模块的加载都会进行一次http请求,那么当模块数量倍增的时候,会拖慢页面的加载速度. 通常我们为了能加快页 ...

随机推荐

  1. numpy.clip(a, a_min, a_max, out=None)(values < a_min are replaced with a_min, and those > a_max with a_max.)

    numpy.clip(a, a_min, a_max, out=None) Clip (limit) the values in an array. Given an interval, values ...

  2. TOJ 3134: 渊子赛马修改版

    3134: 渊子赛马修改版 Time Limit(Common/Java):1000MS/3000MS     Memory Limit:65536KByteTotal Submit: 458     ...

  3. 九度oj 题目1159:坠落的蚂蚁

    题目描述: 一根长度为1米的木棒上有若干只蚂蚁在爬动.它们的速度为每秒一厘米或静止不动,方向只有两种,向左或者向右.如果两只蚂蚁碰头,则它们立即交换速度并继续爬动.三只蚂蚁碰头,则两边的蚂蚁交换速度, ...

  4. nginx的报错500

    500:服务器内部错误,也就是服务器遇到意外情况,而无法履行请求. 500错误一般有几种情况: 1. web脚本错误,如php语法错误,lua语法错误等. 2. 访问量大的时候,由于系统资源限制,而不 ...

  5. uva 11916 解模方程a^x=b (mod n)

      Emoogle Grid  You have to color an M x N ( 1M, N108) two dimensional grid. You will be provided K  ...

  6. SPOJ 4060 A game with probability

    博弈论+dp+概率 提交链接- 题意不是很好懂 Ai 表示剩 i 个石头. A 先手的获胜概率. Bi 表示剩 i 个石头. B先手的获胜概率. 如果想选,对于 Ai: 有 p 的概率进入 Bi−1 ...

  7. *Codeforces989D. A Shade of Moonlight

    数轴上$n \leq 100000$个不重叠的云,给坐标,长度都是$l$,有些云速度1,有些云速度-1,风速记为$w$,问在风速不大于$w_{max}$时,有几对云可能在0相遇.每一对云单独考虑. 多 ...

  8. vs2005做的留言本——天轰川下载

    原文发布时间为:2008-08-01 -- 来源于本人的百度文章 [由搬家工具导入] 这个虽然单纯是个留言本,但是在功能上我都使用了尽量不重复的解决方法,所以我自认为非常适合入门级的朋友看,而且用了我 ...

  9. 2-sat问题,输出方案,几种方法(赵爽的论文染色解法+其完全改进版)浅析 / POJ3683

    本文原创于  2014-02-12 09:26. 今复习之用,有新体会,故重新编辑. 2014-02-12 09:26: 2-sat之第二斩!昨天看了半天论文(赵爽的和俉昱的),终于看明白了!好激动有 ...

  10. Leetcode 数组问题:删除排序数组内的重复项

    问题描述: 给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度. 不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成 ...