代码之家  ›  专栏  ›  技术社区  ›  matt.mercieca

IIS 7托管模块无法获取发送的内容长度或字节数

  •  7
  • matt.mercieca  · 技术社区  · 17 年前

    我有一个针对IIS6的ISAPI过滤器,它使用响应的bytes sent字段执行一些自定义处理。我想为IIs7更新它,但我遇到了一个问题。似乎没有任何一个IIs7事件可以访问内容长度、发送的字节或任何可以让我计算内容长度或发送的字节的数据。(我知道Content-Length头和发送的字节不相同,但这两者都适用。)

    据我所知,在托管模块完成执行后,HTTP.sys会添加Content-Length头。现在我有一个事件处理程序,它在endrequest上运行。如果我能得到输出流,我就可以计算出我自己需要什么,但是被管理的管道似乎也不能访问它。

    是否有某种方法来获取在托管管道中发送的内容长度或字节?如果失败,是否有某种方法可以计算从托管管道中可用的对象发送的内容长度或字节?

    1 回复  |  直到 17 年前
        1
  •  7
  •   Daniel Richardson    17 年前

    要获取发送的字节,可以使用 HttpResponse.Filter 财产。正如msdn文档所说,此属性获取或设置一个包装过滤器对象,该对象用于在传输之前修改HTTP实体体。

    您可以创建一个新的 System.IO.Stream 把现有的 HttpResponse.Filter 流并统计传入到 Write 方法。例如:

    public class ContentLengthModule : IHttpModule
    {
        public void Init(HttpApplication context)
        {
            context.BeginRequest += OnBeginRequest;
            context.EndRequest += OnEndRequest;
        }
    
        void OnBeginRequest(object sender, EventArgs e)
        {
            var application = (HttpApplication) sender;
            application.Response.Filter = new ContentLengthFilter(application.Response.Filter);
        }
    
        void OnEndRequest(object sender, EventArgs e)
        {
            var application = (HttpApplication) sender;
            var contentLengthFilter = (ContentLengthFilter) application.Response.Filter;
            var contentLength = contentLengthFilter.BytesWritten;
        }
    
        public void Dispose()
        {
        }
    }
    
    public class ContentLengthFilter : Stream
    {
        private readonly Stream _responseFilter;
    
        public int BytesWritten { get; set; }
    
        public ContentLengthFilter(Stream responseFilter)
        {
            _responseFilter = responseFilter;
        }
    
        public override void Flush()
        {
            _responseFilter.Flush();
        }
    
        public override long Seek(long offset, SeekOrigin origin)
        {
            return _responseFilter.Seek(offset, origin);
        }
    
        public override void SetLength(long value)
        {
            _responseFilter.SetLength(value);
        }
    
        public override int Read(byte[] buffer, int offset, int count)
        {
            return _responseFilter.Read(buffer, offset, count);
        }
    
        public override void Write(byte[] buffer, int offset, int count)
        {
            BytesWritten += count;
            _responseFilter.Write(buffer, offset, count);
        }
    
        public override bool CanRead
        {
            get { return _responseFilter.CanRead; }
        }
    
        public override bool CanSeek
        {
            get { return _responseFilter.CanSeek; }
        }
    
        public override bool CanWrite
        {
            get { return _responseFilter.CanWrite; }
        }
    
        public override long Length
        {
            get { return _responseFilter.Length; }
        }
    
        public override long Position
        {
            get { return _responseFilter.Position; }
            set { _responseFilter.Position = value; }
        }
    }