利用HttpModule和ResponseFilter來壓縮你的html
阿新 • • 發佈:2019-02-03
不知道大家有沒有注意過google和baidu首頁頁面的html,開啟一看你會發現,竟然沒有縮排什麼,幾乎整個頁面輸出都快寫成一行了,至於為什麼這樣做,我能想到的是節省流量,沒別的想法了.那我們是不是也可以做到這樣呢(雖然我們對流量沒什麼要求),當然是可以的,寫程式碼的時候不要縮排,把html全部寫在一行不就行了,當然這個方法的確可行,但是麻煩了點,而且維護起來也不方便.有沒有更好的辦法,當然是有,我們就利用HttpModule和Response.Filter來實現這個功能吧,廢話說完了,切入正題.
2using System.Collections.Generic;
3using System.Text;
4using System.Web;
5
6namespace K2046.Handlers
7{
8 publicclass FilterModule : IHttpModule
9 {
10 #region IHttpModule 成員11
12 publicvoid Dispose()
13 {
14 // Do Nothing.15 }16
17 publicvoid 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 #endregion31 }32} <add name="ResponseFilter" type="K2046.Handlers.FilterModule, K2046.Handlers"/>3 </httpModules>
2using System.Collections.Generic;
3using System.Text;
4using System.IO;
5using System.Text.RegularExpressions;
6
7namespace K2046.Handlers
8{
9 publicclass ResponseFilter : Stream
10 {
11 private Stream _StreamFilter;
12
13 private ResponseFilter() { }14
15 public ResponseFilter(Stream stream)
16 {
17 _StreamFilter = stream;
18 }19
20 publicoverridebool CanRead
21 {
22 get{ returntrue; }23 }24
25 publicoverridebool CanSeek
26 {
27 get{ returntrue; }28 }29
30 publicoverridebool CanWrite
31 {
32 get{ returntrue; }33 }34
35 publicoverridevoid Flush()
36 {
37 _StreamFilter.Flush();
38 }39
40 publicoverridelong Length
41 {
42 get43 {
44 return _StreamFilter.Length;
45 }46 }47
48 publicoverridelong Position
49 {
50 get51 {
52 return _StreamFilter.Position;
53 }54 set55 {
56 _StreamFilter.Position = value;
57 }58 }59
60 publicoverrideint Read(byte[] buffer, int offset, int count)
61 {
62 return _StreamFilter.Read(buffer, offset, count);
63 }64
65 publicoverridelong Seek(long offset, SeekOrigin origin)
66 {
67 return _StreamFilter.Seek(offset, origin);
68 }69
70 publicoverridevoid SetLength(long value)
71 {
72 _StreamFilter.SetLength(value);
73 }74
75 publicoverridevoid 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
既然是用HttpModule,那當然就得弄個實現了IHttpModule的類了:
1using System;2using System.Collections.Generic;
3using System.Text;
4using System.Web;
5
6namespace K2046.Handlers
7{
8 publicclass FilterModule : IHttpModule
9 {
10 #region IHttpModule 成員11
12 publicvoid Dispose()
13
14 // Do Nothing.15 }16
17 publicvoid 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
25 if (true)//這裡看情況加上你的條件,要不然所有的請求都會被處理,會造成其它檔案型別的輸出異常.26{
27 app.Response.Filter =new ResponseFilter(app.Response.Filter);
28 }29 }30 #endregion31 }32}
在Web.Config的<system.web>中再加上如下程式碼:
1<httpModules>2在這裡面用到了一個ResponseFilter的類,這個也是自己實現的,程式碼如下:
1using System;2using System.Collections.Generic;
3using System.Text;
4using System.IO;
5using System.Text.RegularExpressions;
6
7namespace K2046.Handlers
8{
9 publicclass ResponseFilter : Stream
10 {
11 private Stream _StreamFilter;
12
13 private ResponseFilter() { }14
15 public ResponseFilter(Stream stream)
16 {
17 _StreamFilter = stream;
18 }19
20 publicoverridebool CanRead
21 {
22 get{ returntrue; }23 }24
25 publicoverridebool CanSeek
26 {
27 get{ returntrue; }28 }29
30 publicoverridebool CanWrite
31 {
32 get{ returntrue; }33 }34
35 publicoverridevoid Flush()
36 {
37 _StreamFilter.Flush();
38 }39
40 publicoverridelong Length
41 {
42 get43 {
44 return _StreamFilter.Length;
45 }46 }47
48 publicoverridelong Position
49 {
50 get51 {
52 return _StreamFilter.Position;
53 }54 set55 {
56 _StreamFilter.Position = value;
57 }58 }59
60 publicoverrideint Read(byte[] buffer, int offset, int count)
61 {
62 return _StreamFilter.Read(buffer, offset, count);
63 }64
65 publicoverridelong Seek(long offset, SeekOrigin origin)
66 {
67 return _StreamFilter.Seek(offset, origin);
68 }69
70 publicoverridevoid SetLength(long value)
71 {
72 _StreamFilter.SetLength(value);
73 }74
75 publicoverridevoid 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的資料也不多,有些也說得不是那麼清楚,所以,做個筆記.
posted on 2008-07-22 14:07 狼Robot 閱讀(1986) 評論(28) 編輯 收藏 所屬分類: C#