利用HttpModule和ResponseFilter来压缩你的html
不知道大家有没有注意过google和baidu首页页面的html,打开一看你会发现,竟然没有缩排什么,几乎整个页面输出都快写成一行了,至于为什么这样做,我能想到的是节省流量,没别的想法了.那我们是不是也可以做到这样呢(虽然我们对流量没什么要求),当然是可以的,写代码的时候不要缩排,把html全部写在一行不就行了,当然这个方法的确可行,但是麻烦了点,而且维护起来也不方便.有没有更好的办法,当然是有,我们就利用HttpModule和Response.Filter来实现这个功能吧,废话说完了,切入正题.
既然是用HttpModule,那当然就得弄个实现了IHttpModule的类了:
2using System.Collections.Generic;
3using System.Text;
4using System.Web;
5
6namespace K2046.Handlers
7{
8 public class FilterModule : IHttpModule
9 {
10 IHttpModule 成员
31 }
32}
在Web.Config的<system.web>中再加上如下代码:
2 <add name="ResponseFilter" type="K2046.Handlers.FilterModule, K2046.Handlers"/>
3 </httpModules>
在这里面用到了一个ResponseFilter的类,这个也是自己实现的,代码如下:
2using System.Collections.Generic;
3using System.Text;
4using System.IO;
5using System.Text.RegularExpressions;
6
7namespace K2046.Handlers
8{
9 public class ResponseFilter : Stream
10 {
11 private Stream _StreamFilter;
12
13 private ResponseFilter() { }
14
15 public ResponseFilter(Stream stream)
16 {
17 _StreamFilter = stream;
18 }
19
20 public override bool CanRead
21 {
22 get { return true; }
23 }
24
25 public override bool CanSeek
26 {
27 get { return true; }
28 }
29
30 public override bool CanWrite
31 {
32 get { return true; }
33 }
34
35 public override void Flush()
36 {
37 _StreamFilter.Flush();
38 }
39
40 public override long Length
41 {
42 get
43 {
44 return _StreamFilter.Length;
45 }
46 }
47
48 public override long Position
49 {
50 get
51 {
52 return _StreamFilter.Position;
53 }
54 set
55 {
56 _StreamFilter.Position = value;
57 }
58 }
59
60 public override int Read(byte[] buffer, int offset, int count)
61 {
62 return _StreamFilter.Read(buffer, offset, count);
63 }
64
65 public override long Seek(long offset, SeekOrigin origin)
66 {
67 return _StreamFilter.Seek(offset, origin);
68 }
69
70 public override void SetLength(long value)
71 {
72 _StreamFilter.SetLength(value);
73 }
74
75 public override void Write(byte[] buffer, int offset, int count)
76 {
77 string Html = Encoding.UTF8.GetString(buffer);
78 Html = Regex.Replace(Html, @">\s+?<", "><");//去除Html中的空白字符.
79 Html = Regex.Replace(Html, @"\r\n\s*", "");
80 Html = Regex.Replace(Html, @"<body([\s|\S]*?)>([\s|\S]*?)</body>", @"<body$1>$2<!--Hello,Robot!--></body>", RegexOptions.IgnoreCase);
81 buffer = Encoding.UTF8.GetBytes(Html);
82 _StreamFilter.Write(buffer, offset, buffer.Length);
83 }
84 }
85}
86
其实这个类没做什么,继承Stream,重写Write方法,就可以了,不过关键的就是这里了,在Write的时候,先把byte[]转成string,再把这个string按你想要的方式处理,你想把它整成什么样就整成什么样了.处理完了,再把string转成byte[],然后写入原来的stream里,就OK了.
我现在只是把一些空白字符去掉了,还可以干什么就看自己需要了.
注意:在FilterModule里,所有的请求都会被ResponseFilter处理,包括axd文件什么的,所以会造成输出有问题,所以在加ResponseFilter的时候自己要处理一下条件.
第一次发.NET的文章,写得不好请大家见谅,欢迎各位砖家指点.谢谢.
更新:其实记录这篇文章的原意是实现如何改写输出的流,没找到合适的东西,就用在压缩html上了,当然,也只是简单的去除了空白字符而已,重要的是实现在HttpModule里改写了输出的流.因为之前有碰到过这样的问题,找相关Response.Filter的资料也不多,有些也说得不是那么清楚,所以,做个笔记.