利用HttpModule和ResponseFilter来压缩你的html

  不知道大家有没有注意过google和baidu首页页面的html,打开一看你会发现,竟然没有缩排什么,几乎整个页面输出都快写成一行了,至于为什么这样做,我能想到的是节省流量,没别的想法了.那我们是不是也可以做到这样呢(虽然我们对流量没什么要求),当然是可以的,写代码的时候不要缩排,把html全部写在一行不就行了,当然这个方法的确可行,但是麻烦了点,而且维护起来也不方便.有没有更好的办法,当然是有,我们就利用HttpModule和Response.Filter来实现这个功能吧,废话说完了,切入正题.

 

  既然是用HttpModule,那当然就得弄个实现了IHttpModule的类了:

 1using System;
 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>中再加上如下代码:

1<httpModules>
2            <add name="ResponseFilter" type="K2046.Handlers.FilterModule, K2046.Handlers"/>
3        </httpModules>

 

  在这里面用到了一个ResponseFilter的类,这个也是自己实现的,代码如下:

 1using System;
 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的资料也不多,有些也说得不是那么清楚,所以,做个笔记.

 

Demo项目下载.

posted @ 2008-07-22 14:07  I,Robot  Views(4293)  Comments(30Edit  收藏  举报