zoukankan      html  css  js  c++  java
  • .net中自定义过滤器对Response内容进行处理

    原文:http://www.cnblogs.com/zgqys1980/archive/2008/09/02/1281895.html

    代码DEMO:http://files.cnblogs.com/peaceli/httpModuleTest.rar

    因项目需要,对每一个访问网站的请求要做原始数据记录,其中要包括几个要素:
    1.客户端的IP
    2.客户端请求的页面路径
    3.客户端发出的请求头
    4.服务器返回的正文内容。

    在代码设计前分析了一下,前三个都很好解决,对于截获服务器返回的正文,准备用HttpResponse 对象中的Output 和 OutputStream 属性输出信息来解决。

    可是在正式编码的过程中,发现Output和OutputStream 并不是想像中可以直接把数据转出取回,耗费了近两天的时间,想尽了一切办法可还是仅仅可以追加内容并无法读取。

    在网上查阅到,对于HttpResponse 对象,仅仅可以使用过滤器来对其中将要输出的内容进行修改。
    这个过滤器要继承自Stream 类,并要实现其中的虚方法。看来之前企图使用HttpWriter,TextWriter,Stream,HttpStream 这些类来转出数据完全是错误的。

    现在有信心来截获服务器返回内容了,说干就干吧!

    1.首先要建立一个简易过滤器。
    代码如下:

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Text.RegularExpressions;
    using System.IO;
    using System.Web;

        
    /**////
    <summary>
        
    /// 定义原始数据EventArgs,便于在截获完整数据后,由事件传递数据
        
    ///
    </summary>


    public
    class RawDataEventArgs : EventArgs
        
    {
            
    private
    string sourceCode;

            
    public RawDataEventArgs(string SourceCode)
            
    {
                sourceCode 
    = SourceCode;
            }

            
    public
    string SourceCode
            
    {
                
    get
    return sourceCode; }
                
    set
    { sourceCode = value; }
            }

        }


    //自定义过滤器
        
    public
    class RawFilter : Stream
        
    {

            Stream responseStream;
            
    long position;
            StringBuilder responseHtml;

            
    /**////
    <summary>
            
    /// 当原始数据采集成功后激发。
            
    ///
    </summary>


    public
    event EventHandler<RawDataEventArgs> OnRawDataRecordedEvent;

            
    public RawFilter(Stream inputStream)
            
    {
                responseStream 
    = inputStream;
                responseHtml 
    =
    new StringBuilder();
            }


    //实现Stream 虚方法

    Filter Overrides#region Filter Overrides

            
    public
    override
    bool CanRead
            
    {
                
    get
                
    {
                    
    return
    true;
                }

            }


            
    public
    override
    bool CanSeek
            
    {
                
    get
                
    {
                    
    return
    true;
                }

            }


            
    public
    override
    bool CanWrite
            
    {
                
    get
                
    {
                    
    return
    true;
                }

            }

            
    public
    override
    void Close()
            
    {
                responseStream.Close();
            }


            
    public
    override
    void Flush()
            
    {
                responseStream.Flush();
            }


            
    public
    override
    long Length
            
    {
                
    get
                
    {
                    
    return
    0;
                }

            }


            
    public
    override
    long Position
            
    {
                
    get
                
    {
                    
    return position;
                }

                
    set
                
    {
                    position 
    = value;
                }

            }


            
    public
    override
    int Read(byte[] buffer, int offset, int count)
            
    {
                
    return responseStream.Read(buffer, offset, count);
            }


            
    public
    override
    long Seek(long offset, SeekOrigin origin)
            
    {
                
    return responseStream.Seek(offset, origin);
            }


            
    public
    override
    void SetLength(long length)
            
    {
                responseStream.SetLength(length);
            }

            
    #endregion

    //关键的点,在HttpResponse 输入内容的时候,一定会调用此方法输入数据,所以要在此方法内截获数据

    public
    override
    void Write(byte[] buffer, int offset, int count)
            
    {
                
    string strBuffer = System.Text.UTF8Encoding.UTF8.GetString(buffer, offset, count);

    //采用正则,检查输入的是否有页面结束符</html>
                Regex eof =
    new Regex("</html>", RegexOptions.IgnoreCase);

                
    if (!eof.IsMatch(strBuffer))
                
    {
                  
    //页面没有输出完毕,继续追加内容
                    responseHtml.Append(strBuffer);
                }

                
    else
                
    {
                  
    //页面输出已经完毕,截获内容
                    responseHtml.Append(strBuffer);
                    
    string finalHtml = responseHtml.ToString();

                
    //激发数据已经获取事件
                OnRawDataRecordedEvent(thisnew RawDataEventArgs(finalHtml));

                    
    //继续传递要发出的内容写入流

    byte[] data = System.Text.UTF8Encoding.UTF8.GetBytes(finalHtml);

                    responseStream.Write(data, 
    0, data.Length);
                }

            }

        }

    至此,过滤器定义完毕了,接下来还需要把这个过滤器装配到HttpResponse 对象中。
    为了能够截获整站的aspx 页面输出的内容,我们可以定义一个HttpModule 来完成。
    代码如下:

    using System;
    using System.Web;
    using System.Collections.Generic;
    using System.Text;
    using System.IO;
    using System.Diagnostics;

        
    public
    class HttpRawDataModule : IHttpModule
        
    {
            
    IHttpModule 成员#region IHttpModule 成员

            
    public
    void Dispose()
            
    {

            }


            
    public
    void Init(HttpApplication context)
            
    {
                
    //绑定事件,在对此请求处理过程全部结束后进行过滤操作
                context.ReleaseRequestState +=
    new EventHandler(context_ReleaseRequestState);
            }


            
    #endregion

            
    /**////
    <summary>
            
    /// 对此HTTP请求处理的过程全部结束
            
    ///
    </summary>
            
    ///
    <param name="sender"></param>
            
    ///
    <param name="e"></param>


    void context_ReleaseRequestState(object sender, EventArgs e)
            
    {
                HttpApplication application 
    = (HttpApplication)sender;

                
    //这里需要针对ASPX页面进行拦截,测试发现如果不这么做,Wap 访问站点图片容易显示为X,奇怪

    string[] temp = application.Request.CurrentExecutionFilePath.Split('.');
                
    if (temp.Length >
    0
    && temp[temp.Length -
    1].ToLower() ==
    "aspx")
                
    {
                    
    //装配过滤器
                    application.Response.Filter =
    new RawFilter(application.Response.Filter);

                    
    //绑定过滤器事件
                    RawFilter filter = (RawFilter)application.Response.Filter;
                    filter.OnRawDataRecordedEvent 
    +=
    new EventHandler<RawDataEventArgs>(filter_OnRawDataRecordedEvent);
                }

            }


            
    /**////
    <summary>
            
    /// 当原始数据采集到以后,入库 
            
    ///
    </summary>
            
    ///
    <param name="sender"></param>
            
    ///
    <param name="e"></param>


    void filter_OnRawDataRecordedEvent(object sender, RawDataEventArgs e)
            
    {
                
    string allcode = e.SourceCode;
                WapSite.SiteDataClass wapdata 
    =
    new WapSite.SiteDataClass();
                wapdata.WriteRawDataLog(allcode);
            }

        }


    HttpModule 准备完毕,也装配上了过滤器,接下来还需要在配置文件中配置HttpModules配置节 ,把自定义的HttpModule 加入到HTTP处理管道中。
    在Web.config 中增加配置节如下:


    <system.web>
        
    <httpModules>
          
    <add name="RawDataModule" type="HttpRawDataModule"/>
        
    </httpModules>
      
    </system.web>


    测试成功,能准确的获得服务器向客户端输出的HTML内容。

    其中,在过滤器中,可以直接对即将要输出的内容做 对于字符串的任意处理。

    而且采用这样的方式来对站点即将输出的内容做修改和采集,可以通过修改配置文件,随时打开和关闭,有很强的优越性和灵活性还有重用性。

    记得看到过很多需要产生静态页面的网站,都是通过代码HttpWebRequest 向自己请求并记录返回的代码产生静态页面,不知道我当前介绍的方法是否更好写,比如需要产生静态页面时,不管是谁发出请求,由服务器检查自己是否有静态页面,否则产生静态页面,并转向。给出引子,希望大家还是自己开阔思路比较好。
     

     .net中自定义过滤器对Response内容进行处理

  • 相关阅读:
    使用knockout.js 完毕template binding
    站点建设价格为什么有高有低?站点建设该怎样选择?
    同余 模算术 中国剩余定理
    linux 命令之 apt-get
    [Leetcode]-Reverse Integer
    《Python入门》Windows 7下Python Web开发环境搭建笔记
    javascript之Ajax起步
    SQL server 2012 安装SQL2012出现报错: 启用 Windows 功能 NetFx3 时出错
    C# 反射具体解释
    java8_api_jni
  • 原文地址:https://www.cnblogs.com/moonvan/p/3578814.html
Copyright © 2011-2022 走看看