• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

ASP.Net重写IHttpModule来拦截HttpApplication实现HTML资源压缩和空白过滤 ...

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

务实直接上代码:

1. 重写FilterModule.cs

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 using System.Web;
 7 using System.Text.RegularExpressions;
 8 using System.IO.Compression;
 9 
10 namespace Compress.FilterModule
11 {
12     public class FilterModule : IHttpModule
13     {
14         public void Dispose()
15         {
16             //
17         }
18 
19         /// <summary>
20         /// Init method is only used to register the desired event
21         /// </summary>
22         /// <param name="context"></param>
23         public void Init(HttpApplication context)
24         {
25             context.BeginRequest += new EventHandler(context_BeginRequest);
26             //context.EndRequest += new EventHandler(context_EndRequest);
27             //context.PostRequestHandlerExecute += new EventHandler(context_PostRequestHandlerExecute);
28         }
29 
30 
31         /// <summary>
32         /// Handles the BeginRequest event of the context control.
33         /// </summary>
34         /// <param name="sender">The source of the event.</param>
35         /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
36         void context_BeginRequest(object sender, EventArgs e)
37         {
38             HttpApplication app = sender as HttpApplication;
39             HttpContext context = app.Context;
40             if (context.CurrentHandler is System.Web.UI.Page)
41             {
42                 bool isPage = context.CurrentHandler.IsReusable;
43             }
44             if (app.Request.RawUrl.Contains(".aspx") || app.Request.RawUrl.EndsWith("/"))
45             {
46                 // HttpContext context = app.Context;
47                 HttpRequest request = context.Request;
48                 string acceptEncoding = request.Headers["Accept-Encoding"];
49                 HttpResponse response = context.Response;
50                 if (!string.IsNullOrEmpty(acceptEncoding))
51                 {
52                     acceptEncoding = acceptEncoding.ToUpperInvariant();
53                     if (acceptEncoding.Contains("GZIP"))
54                     {
55                         //var straem = new GZipStream(response.Filter, CompressionMode.Compress);
56                         response.Filter = new CompressWhitespaceFilter(response.Filter, CompressOptions.GZip);
57                         response.AppendHeader("Content-encoding", "gzip");
58                     }
59                     else if (acceptEncoding.Contains("DEFLATE"))
60                     {
61                         response.Filter = new CompressWhitespaceFilter(context.Response.Filter, CompressOptions.Deflate);
62                         response.AppendHeader("Content-encoding", "deflate");
63                     }
64                 }
65                 response.Cache.VaryByHeaders["Accept-Encoding"] = true;
66             }
67         }
68 
69         // Test
70         //void context_BeginRequest(object sender, EventArgs e)
71         //{
72         //    HttpApplication application = (HttpApplication)sender;
73         //    HttpContext context = application.Context;
74         //    context.Response.ContentType = "text/html";
75         //    context.Response.Charset = "GB2312";
76         //    context.Response.ContentEncoding = Encoding.Default;
77         //    context.Response.Write("<h1 style='color:#00f'>Treatment from HttpModule,Begin...</h1><hr>");
78         //}
79 
80         // Test
81         //void context_EndRequest(object sender, EventArgs e)
82         //{
83         //    HttpApplication application = (HttpApplication)sender;
84         //    HttpContext context = application.Context;
85         //    context.Response.ContentType = "text/html";
86         //    context.Response.Charset = "GB2312";
87         //    context.Response.ContentEncoding = Encoding.Default;
88         //    context.Response.Write("<hr><h1 style='color:#f00'>Treatment from HttpModule,End...</h1>");
89         //}
90 
91     }
92 }

 

2. 处理压缩和匹配自定义过滤 CompressWhitespaceFilter.cs

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Linq;
  4 using System.Web;
  5 using System.IO;
  6 using System.Text;
  7 using System.Text.RegularExpressions;
  8 using System.IO.Compression;
  9 
 10 namespace Compress.ModuleDemo
 11 {
 12     public enum CompressOptions
 13     {
 14         GZip,
 15         Deflate,
 16         None
 17     }
 18 
 19     public class CompressWhitespaceFilter : Stream
 20     {
 21         StringBuilder responseHtml;
 22         const string _cssPattern = "(?<HTML><link[^>]*href\\s*=\\s*[\\\"\\']?(?<HRef>[^\"'>\\s]*)[\\\"\\']?[^>]*>)";
 23         const string _jsPattern = "(?<HTML><script[^>]*src\\s*=\\s*[\\\"\\']?(?<SRC>[^\"'>\\s]*)[\\\"\\']?[^>]*></script>)";
 24 
 25         private HttpApplication app;
 26         public HttpApplication App
 27         {
 28             get { return app; }
 29             set { app = value; }
 30         }
 31 
 32         private GZipStream _contentGZip;
 33         private DeflateStream _content_Deflate;
 34         private Stream _content;
 35         private CompressOptions _options;
 36         private bool disposed = false;
 37 
 38         private CompressWhitespaceFilter() { }
 39         public CompressWhitespaceFilter(Stream content, CompressOptions options)
 40         {
 41 
 42             responseHtml = new StringBuilder();
 43             if (options == CompressOptions.GZip)
 44             {
 45                 this._contentGZip = new GZipStream(content, CompressionMode.Compress, true);
 46                 this._content = this._contentGZip;
 47             }
 48             else if (options == CompressOptions.Deflate)
 49             {
 50                 this._content_Deflate = new DeflateStream(content, CompressionMode.Compress, true);
 51                 this._content = this._content_Deflate;
 52             }
 53             else
 54             {
 55                 this._content = content;
 56             }
 57             this._options = options;
 58         }
 59 
 60         public override bool CanRead
 61         {
 62             get { return this._content.CanRead; }
 63         }
 64 
 65         public override bool CanSeek
 66         {
 67             get { return this._content.CanSeek; }
 68         }
 69 
 70         public override bool CanWrite
 71         {
 72             get { return this._content.CanWrite; }
 73         }
 74 
 75         /// <summary>
 76         /// When overriding in a derived class, all buffers of the stream are cleared and all buffer data is written to the underlying device
 77         /// </summary>
 78         public override void Flush()
 79         {
 80             this._content.Flush();
 81             //Test
 82             //this._content.Dispose();
 83             //this._contentGZip.Dispose();
 84         }
 85 
 86 
 87         /// <summary>
 88         /// 重写Dispose方法,释放派生类自己的资源,并且调用基类的Dispose方法
 89         /// 使Gzip把缓存中余下的内容全部写入MemoryStream中,因为只有在Gzip流释放之后才能去承载对象中读取数据或判断数据大小
 90         /// </summary>
 91         /// <param name="disposing"></param>
 92         protected override void Dispose(bool disposing)
 93         {
 94             if (!this.disposed)
 95             {
 96                 try
 97                 {
 98                     if (disposing)
 99                     {
100                         // Release the managed resources you added in this derived class here.
101                         //xx.Dispose();
102                     }
103 
104                     //  Release the native unmanaged resources you added in this derived class here.
105                     //  xx.Close()
106 
107                     //if (_contentGZip != null)
108                     //    _contentGZip.Close();
109 
110                     //if (_content_Deflate != null)
111                     //    _content_Deflate.Close();
112 
113                     this._content.Close();
114                     this.disposed = true;
115                 }
116                 finally
117                 {
118                     // Call Dispose on your base class.
119                     base.Dispose(disposing);
120                 }
121             }
122         }
123 
124         public override long Length
125         {
126             get { return this._content.Length; }
127         }
128 
129         public override long Position
130         {
131             get
132             {
133                 return this._content.Position;
134             }
135             set
136             {
137                 this._content.Position = value;
138             }
139         }
140 
141         public override int Read(byte[] buffer, int offset, int count)
142         {
143             return this._content.Read(buffer, offset, count);
144         }
145 
146         public override long Seek(long offset, SeekOrigin origin)
147         {
148             return this._content.Seek(offset, origin);
149         }
150 
151         public override void SetLength(long value)
152         {
153             this._content.SetLength(value);
154         }
155 
156         public override void Write(byte[] buffer, int offset, int count)
157         {
158             byte[] data = new byte[count + 1];
159             Buffer.BlockCopy(buffer, offset, data, 0, count);
160             string s = System.Text.Encoding.UTF8.GetString(data);
161             s = Regex.Replace(s, "^\\s*", string.Empty, RegexOptions.Compiled | RegexOptions.Multiline);
162             s = Regex.Replace(s, "\\r\\n", string.Empty, RegexOptions.Compiled | RegexOptions.Multiline);
163             s = Regex.Replace(s, "<!--*.*?-->", string.Empty, RegexOptions.Compiled | RegexOptions.Multiline);
164             byte[] outdata = System.Text.Encoding.UTF8.GetBytes(s);
165             this._content.Write(outdata, 0, outdata.GetLength(0));
166         }
167 
168 
169         /// <summary>
170         /// Replcase stylesheet links with ones pointing to HttpHandlers that compress and cache the css
171         /// </summary>
172         /// <param name="html"></param>
173         /// <returns></returns>
174         public string ReplaceCss(string html)
175         {
176             // create a list of the stylesheets
177             List<string> stylesheets = new List<string>();
178             // create a dictionary used for combining css in the same directory
179             Dictionary<string, List<string>> css = new Dictionary<string, List<string>>();
180 
181             // create a base uri which will be used to get the uris to the css
182             Uri baseUri = new Uri(app.Request.Url.AbsoluteUri);
183 
184             // loop through each match
185             foreach (Match match in Regex.Matches(html, _cssPattern, RegexOptions.IgnoreCase))
186             {
187                 // this is the enire match and will be used to replace the link
188                 string linkHtml = match.Groups[0].Value;
189                 // this is the href of the link
190                 string href = match.Groups[2].Value;
191 
192                 // get a uri from the base uri, this will resolve any relative and absolute links
193                 Uri uri = new Uri(baseUri, href);
194                 string file = "";
195                 // check to see if it is a link to a local file
196                 if (uri.Host == baseUri.Host)
197                 {
198                     // check to see if it is local to the application
199                     if (uri.AbsolutePath.ToLower().StartsWith(app.Context.Request.ApplicationPath.ToLower()))
200                     {
201                         // this combines css files in the same directory into one file (actual combining done in HttpHandler)
202                         int index = uri.AbsolutePath.LastIndexOf("/");
203                         string path = uri.AbsolutePath.Substring(0, index + 1);
204                         file = uri.AbsolutePath.Substring(index + 1);
205                         if (!css.ContainsKey(path))
206                             css.Add(path, new List<string>());
207                         css[path].Add(file + (href.Contains("?") ? href.Substring(href.IndexOf("?")) : ""));
208                         // replace the origianl links with blanks
209                         html = html.Replace(linkHtml, "");
210                         // continue to next link
211                         continue;
212                     }
213                     else
214                         file = uri.AbsolutePath + uri.Query;
215                 }
216                 else
217                     file = uri.AbsoluteUri;
218                 string newLinkHtml = linkHtml.Replace(href, "css.axd?files=" + file);
219 
220                 // just replace the link with the new link
221                 html = html.Replace(linkHtml, newLinkHtml);
222             }
223 
224             StringBuilder link = new StringBuilder();
225             link.AppendLine("");
226             foreach (string key in css.Keys)
227             {
228                 link.AppendLine(string.Format("<link href='{0}css.axd?files={1}' type='text/css' rel='stylesheet' />", key, string.Join(",", css[key].ToArray())));
229 
230             }
231 
232             // find the head tag and insert css in the head tag
233             int x = html.IndexOf("<head");
234             int num = 0;
235             if (x > -1)
236             {
237                 num = html.Substring(x).IndexOf(">");
238                 html = html.Insert(x + num + 1, link.ToString());
239             }
240             return html;
241         }
242 
243         /// <summary>
244         /// Replcase javascript links with ones pointing to HttpHandlers that compress and cache the javascript
245         /// </summary>
246         /// <param name="html"></param>
247         /// <returns></returns>
248         public string ReplaceJS(string html)
249         {
250             // if the javascript is in the head section of the html, then try to combine the javascript into one
251             int start, end;
252             if (html.Contains("<head") && html.Contains("</head>"))
253             {
254                 start = html.IndexOf("<head");
255                 end = html.IndexOf("</head>");
256                 string head = html.Substring(start, end - start);
257 
258                 head = ReplaceJSInHead(head);
259 
260                 html = html.Substring(0, start) + head + html.Substring(end);
261             }
262 
263             // javascript that is referenced in the body is usually used to write content to the page via javascript, 
264              
                       
                    
                    

鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
Asp.NetMVC使用FileResult导出Excel数据文件发布时间:2022-07-10
下一篇:
centosasp.net运行环境配置发布时间:2022-07-10
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap