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

{
8
public class FilterModule : IHttpModule
9
{
10
IHttpModule 成员#region IHttpModule 成员
11
12
public void Dispose()
13
{
14
// Do Nothing.
15
}
16
17
public void Init(HttpApplication context)
18
{
19
context.BeginRequest += new EventHandler(Application_BeginRequest);
20
}
21
22
void Application_BeginRequest(object sender, EventArgs e)
23
{
24
HttpApplication app = sender as HttpApplication;
25
if (true)//这里看情况加上你的条件,要不然所有的请求都会被处理,会造成其它文件类型的输出异常.
26
{
27
app.Response.Filter = new ResponseFilter(app.Response.Filter);
28
}
29
}
30
#endregion
31
}
32
}
在Web.Config的<system.web>中再加上如下代码:
1
<httpModules>
2
<add name="ResponseFilter" type="K2046.Handlers.FilterModule, K2046.Handlers"/>
3
</httpModules>
在这里面用到了一个ResponseFilter的类,这个也是自己实现的,代码如下:
1
using System;
2
using System.Collections.Generic;
3
using System.Text;
4
using System.IO;
5
using System.Text.RegularExpressions;
6
7
namespace 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项目下载.