ActionFilterAttribute之HtmlFilter,压缩HTML代码
当开启这个过滤器后,最终生成的HTML代码将会被压缩一下,在流量很大的网站中,能减少带宽成本就减少一点,何乐而不为?
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Text.RegularExpressions;
- using System.Web.Mvc;
- using Mkt.Common;
- namespace Mkt.Mvc.Filter
- {
- public class HtmlFilter : ActionFilterAttribute
- {
- #region = IsAvailable =
- private bool _isavailable = true;
- public bool IsAvailable
- {
- get { return _isavailable; }
- set { _isavailable = value; }
- }
- #endregion
- public HtmlFilter() { }
- public HtmlFilter(bool isAvailable)
- {
- _isavailable = isAvailable;
- }
- public string SetGray(string text)
- {
- text = Common.HtmlHelper.Compress(text);
- if (DateTime.Now.Month == 4 && DateTime.Now.Day == 21)
- {
- text = Regex.Replace(text, "</head>", @"<style type=""text/css"">html {filter:gray;}</style></head>
- ", RegexOptions.IgnoreCase);
- }
- return text;
- }
- public override void OnActionExecuting(ActionExecutingContext filterContext)
- {
- base.OnActionExecuting(filterContext);
- }
- public override void OnResultExecuted(ResultExecutedContext filterContext)
- {
- base.OnResultExecuted(filterContext);
- if (!IsAvailable) return;
- #if DEBUG
- return;
- #endif
- filterContext.RequestContext.HttpContext.Response.Filter = new HtmlStreamFilter(filterContext.RequestContext.HttpContext.Response.Filter, filterContext.RequestContext.HttpContext.Response.ContentEncoding, SetGray);
- }
- }
- }
compress代码:
- /// <summary>
- /// 压缩html代码
- /// </summary>
- /// <param name="text">The text.</param>
- /// <returns></returns>
- public static string Compress(string text)
- {
- text = Regex.Replace(text, @"<!--\S*?-->", string.Empty);
- text = Regex.Replace(text, @"^\s+|\s+{1}quot;, string.Empty);
- text = Regex.Replace(text, "\n", " ");
- text = Regex.Replace(text, @">\s+?<", "><");
- text = Regex.Replace(text, @"\s{2,}", " ");
- text = Regex.Replace(text, " {2,}", @"\s");
- text = Regex.Replace(text, @"\s{2,}", @"\s");
- return text;
- }
其中的SetGray是4.21哀悼日变灰设置.
配合CompressFilter,效果更佳~
之前露掉了HtmlStreamFilter的源码,如下:
- public class HtmlStreamFilter : Stream
- {
- Stream responseStream;
- long position;
- StringBuilder responseHtml;
- #region = CurrentEncoding =
- private Encoding _currentencoding;
- public Encoding CurrentEncoding
- {
- get { return _currentencoding; }
- set { _currentencoding = value; }
- }
- #endregion
- Func<string, string> _func;
- public HtmlStreamFilter(Stream inputStream, Encoding enc, Func<string, string> func
- )
- {
- responseStream = inputStream;
- _currentencoding = enc;
- _func = func;
- responseHtml = new StringBuilder();
- }
- #region Filter overrides
- public override bool CanRead
- {
- get { return true; }
- }
- public override bool CanSeek
- {
- get { return true; }
- }
- public override bool CanWrite
- {
- get { return true; }
- }
- public override void Close()
- {
- responseStream.Close();
- }
- public override void Flush()
- {
- responseStream.Flush();
- }
- public override long Length
- {
- get { return 0; }
- }
- public override long Position
- {
- get { return position; }
- set { position = value; }
- }
- public override long Seek(long offset, SeekOrigin origin)
- {
- return responseStream.Seek(offset, origin);
- }
- public override void SetLength(long length)
- {
- responseStream.SetLength(length);
- }
- public override int Read(byte[] buffer, int offset, int count)
- {
- return responseStream.Read(buffer, offset, count);
- }
- #endregion
- #region Dirty work
- public override void Write(byte[] buffer, int offset, int count)
- {
- string strBuffer = CurrentEncoding.GetString(buffer, offset, count);
- #region =如果不是HTML文档,不作处理=
- var bof = new Regex("<html", RegexOptions.IgnoreCase);
- if (!bof.IsMatch(responseHtml.ToString()))
- {
- responseStream.Write(buffer, offset, count);
- return;
- }
- #endregion
- // ---------------------------------
- // Wait for the closing </html> tag
- // ---------------------------------
- Regex eof = new Regex("</html>", RegexOptions.IgnoreCase);
- if (!eof.IsMatch(strBuffer))
- {
- responseHtml.Append(strBuffer);
- }
- else
- {
- responseHtml.Append(strBuffer);
- string finalHtml = responseHtml.ToString();
- finalHtml = _func(finalHtml);
- // Transform the response and write it back out
- byte[] data = CurrentEncoding.GetBytes(finalHtml);
- responseStream.Write(data, 0, data.Length);
- }
- }
- #endregion
- }
第二种方法,使用.net内部类实现:
- public class HtmlFilter : ActionFilterAttribute
- {
- #region = IsAvailable =
- private bool _isavailable = true;
- public bool IsAvailable
- {
- get { return _isavailable; }
- set { _isavailable = value; }
- }
- #endregion
- private TextWriter _originalWriter;
- private static readonly MethodInfo SwitchWriterMethod = typeof(HttpResponse).GetMethod("SwitchWriter", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
- public HtmlFilter() { }
- public HtmlFilter(bool isAvailable)
- {
- _isavailable = isAvailable;
- }
- public string SetGray(string text)
- {
- text = Common.HtmlHelper.Compress(text);
- if (DateTime.Now.Month == 4 && DateTime.Now.Day == 21)
- {
- text = Regex.Replace(text, "</head>", @"<style type=""text/css"">html {filter:gray;}</style></head>
- ", RegexOptions.IgnoreCase);
- }
- return text;
- }
- public override void OnActionExecuting(ActionExecutingContext filterContext)
- {
- if (!IsAvailable) return;
- #if DEBUG
- return;
- #endif
- _originalWriter = (TextWriter)SwitchWriterMethod.Invoke(HttpContext.Current.Response, new object[] { new HtmlTextWriter(new StringWriter()) });
- base.OnActionExecuting(filterContext);
- }
- public override void OnResultExecuted(ResultExecutedContext filterContext)
- {
- base.OnResultExecuted(filterContext);
- if (!IsAvailable) return;
- #if DEBUG
- return;
- #endif
- HtmlTextWriter cacheWriter = (HtmlTextWriter)SwitchWriterMethod.Invoke(HttpContext.Current.Response, new object[] { _originalWriter });
- string textWritten = cacheWriter.InnerWriter.ToString();
- if (filterContext.HttpContext.Response.ContentType == "text/html")
- {
- textWritten = Compress(textWritten).ToString();
- }
- filterContext.HttpContext.Response.Write(textWritten);
- //filterContext.RequestContext.HttpContext.Response.Filter = new HtmlStreamFilter(filterContext.RequestContext.HttpContext.Response.Filter, filterContext.RequestContext.HttpContext.Response.ContentEncoding, SetGray);
- }
- private static StringBuilder Compress(string text)
- {
- StringBuilder str = new StringBuilder();
- StringBuilder strlink = new StringBuilder();
- var s = new char[] { '\f', '\n', '\r', '\t', '\v' };
- Func<int, object> P = c => null;
- Func<int, object> Ptag = c => null; //标签处理机
- Func<int, object> Pcomment = c => null; //注释
- #region - 总处理机 -
- Func<int, object> state = P = i =>
- {
- char c = text[i];
- if (c == '<') //碰到<交个Ptag处理机
- {
- if (i + 4 < text.Length)
- {
- if (text.Substring(i + 1, 3) == "!--") //交个注释处理机
- {
- return Pcomment;
- }
- }
- str.Append(c);
- return Ptag;
- }
- else if (s.Contains(c) == true) { return P; }
- else if (c == ' ')
- {
- if (i + 1 < text.Length)
- {
- if (s.Union(new char[] { ' ', '<' }).Contains(text[i + 1]) == false)
- {
- str.Append(c);
- }
- }
- return P;
- }
- else
- {
- str.Append(c);
- return P;
- }
- };
- #endregion
- #region - Tag处理机 -
- Ptag = i =>
- {
- char c = text[i];
- if (c == '>') //交还给p
- {
- str.Append(c);
- return P;
- }
- else if (s.Contains(c) == true) { return Ptag; }
- else if (c == ' ')
- {
- if (i + 1 < text.Length)
- {
- if (new char[] { ' ', '/', '=', '>' }.Contains(text[i + 1]) == false)
- {
- str.Append(c);
- }
- }
- return Ptag;
- }
- else
- {
- str.Append(c);
- return Ptag;
- }
- };
- #endregion
- #region - 注释处理机 -
- Pcomment = i =>
- {
- char c = text[i];
- if (c == '>' && text.Substring(i - 2, 3) == "-->")
- {
- return P;
- }
- else
- {
- return Pcomment;
- }
- };
- #endregion
- for (int index = 0; index < text.Length; index++)
- {
- state = (Func<int, object>)state(index);
- }
- return str;
- }
- }
此方法中新的compress方法使用的GoodSpeed的成果.
ActionFilterAttribute之HtmlFilter,压缩HTML代码的更多相关文章
- js数组特定位置元素置空,非null和undefined,实现echarts现状图效果;谷歌格式化压缩js代码
一.想要实现eCharts线状图表的断点效果,如图(后来又查到数据格式为data:['-', 2, 3,'-' , 5, 6, 7]:也可以断点显示) 这种效果,在设置数据的时候应该是这样: data ...
- Linux oracle数据库自动备份自动压缩脚本代码
Linux oracle数据库备份完成后可以自动压缩脚本代码. 复制代码代码如下: #!/bin/bash #backup.sh #edit: www.jbxue.com ##系统名称 sysname ...
- javascript 压缩空格代码演示
压缩空格代码演示 主要是讲解 压缩一个字符串两段空格 例如:javascript函数里的空格不论是这样 var s = "Hello World ...
- js、css动态压缩页面代码
1.js.css动态压缩页面代码 <%@ Page Language="C#" AutoEventWireup="true" CodeFile=" ...
- nodejs+gulpjs压缩js代码
1.安装node.js 下载地址:nodejs.org 或者 nodejs.cn 2.安装gulp之前我们需要安装nodejs的环境,检测能够正常使用npm后,我们用npm对gulp进行一次全局安 ...
- Joomla - 优化(时区、google字体、压缩图片、压缩自定义代码)
Joomla - 优化(时区.google字体.压缩图片.压缩自定义代码) 一.时区 发布文章是往往会发现发布时间和当前时间对不上,原因是 Joomla 用的是国际标准时间,和中国时区大约相差8小时, ...
- 使用Google Closure Compiler高级压缩Javascript代码注意的几个地方
介绍 GCC(Google Closure Compiler)是由谷歌发布的Js代码压缩编译工具.它可以做到分析Js的代码,移除不需要的代码(dead code),并且去重写它,最后再进行压缩. 三种 ...
- Source Map调试压缩后代码
在前端开发过程中,无论是样式还是脚本,运行时的文件可能是压缩后的,那这个时候调试起来就很麻烦. 这个时候,可以使用Source Map文件来优化调试,Source Map是一个信息文件,里面储存着原代 ...
- 打包并压缩seajs代码
背景 seajs是一款优秀的模块开发插件,但是当我们使用它来进行模块化开发的时候,由于它的每个模块的加载都会进行一次http请求,那么当模块数量倍增的时候,会拖慢页面的加载速度. 通常我们为了能加快页 ...
随机推荐
- luogu2216 [HAOI2007]理想的正方形
先对于每一行中长度为 n 的列用单调队列搞出它们的最小/大值,再将这些长度为 n 的列想象成点再对行跑一遍 #include <iostream> #include <cstring ...
- SPOJ - ADAQUEUE ,双端队列简单运用!
ADAQUEUE - Ada and Queue 表示这题是学弟带的榜,题还没看完,学弟吐了一句:这不就是双端队列嘛.于是掏出布满尘埃的<曾粽根ACM程序设计>,嗯,确实是裸题,现学现做. ...
- POJ-1743 Musical Theme,后缀数组+二分!
Musical Theme 人生第一道后缀数组的题,采用大众化思想姿势极其猥琐. 题意:给你n个 ...
- oracle用户密码错误导致用户锁定
解决方法:使用DBA用户将其解锁: SQL> alter user ecology account unlock; 用户已更改. 用户密码限制设置: 查看FAILED_LOGIN_ATTEMPT ...
- [UOJ#219][BZOJ4650][Noi2016]优秀的拆分
[UOJ#219][BZOJ4650][Noi2016]优秀的拆分 试题描述 如果一个字符串可以被拆分为 AABBAABB 的形式,其中 A 和 B 是任意非空字符串,则我们称该字符串的这种拆分是优秀 ...
- mysql5.7.23版本环境配置
亲身实践安装mysql,用时居然花费了三个小时,在有那么多教程的情况下,依然在不该花费时间的路上浪费了太多时间.希望这篇文章能够帮助大家少走弯路~~ 1.下载我下载的是64位. 2.解压下载之后,我选 ...
- 【loj6191】「美团 CodeM 复赛」配对游戏
题目 显然期望dp. 简单想法: f[i][j]表示前i个人中向右看并且没有被消除的人数的概率 如果第i+1个人是向右,$f[i+1][j+1]=f[i][j]/2$ 如果第i+1个人是向左,$f[i ...
- 设置好uTorrent让你的下载速度飞起来
由于有会员反映下载国外种子速度很慢的问题,而我下同样的种子,竟然那天下载最高速度能到500K/秒.(我用的是移动的校园网,这种出了名的烂网,十天有七天是图片都打不开的网)这可见是所用软件和软件的设置问 ...
- [C/C++] 结构体内存对齐用法
一.为什么要内存对齐 经过内存对齐之后,CPU的内存访问速度大大提升; 内存空间按照byte划分,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定变量的时候经常在特定的内 ...
- Mac快速查看隐藏文件
使用终端 显示隐藏文件的最简单方法是使用终端.只要打开终端(位于应用程序--实用工具),将以下代码复制进去然后回车 defaults write com.apple.finder AppleShowA ...