在PreRequestHandlerExecute 事件里边用DeflateStream修饰的Response.Filter替代Response.Filter
  public sealed class CompressionModule : IHttpModule
  {

#region IHttpModule Members

/// <summary>
    /// Disposes of the resources (other than memory) used by the module
    /// that implements <see cref="T:System.Web.IHttpModule"></see>.
    /// </summary>
    void IHttpModule.Dispose()
    {
      // Nothing to dispose;
    }

/// <summary>
    /// Initializes a module and prepares it to handle requests.
    /// </summary>
    /// <param name="context">An <see cref="T:System.Web.HttpApplication"></see>
    /// that provides access to the methods, properties, and events common to
    /// all application objects within an ASP.NET application.
    /// </param>
    void IHttpModule.Init(HttpApplication context)
    {
      if (BlogSettings.Instance.EnableHttpCompression)
      {
        context.PreRequestHandlerExecute += new EventHandler(context_PostReleaseRequestState);
      }
    }

#endregion

private const string GZIP = "gzip";
    private const string DEFLATE = "deflate";

#region Compress page

/// <summary>
    /// Handles the BeginRequest event of the context control.
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
    void context_PostReleaseRequestState(object sender, EventArgs e)
    {
      HttpApplication app = (HttpApplication)sender;
      if (app.Context.CurrentHandler is System.Web.UI.Page && app.Request["HTTP_X_MICROSOFTAJAX"] == null)
      {
        if (IsEncodingAccepted(DEFLATE))
        {
          app.Response.Filter = new DeflateStream(app.Response.Filter, CompressionMode.Compress);
          SetEncoding(DEFLATE);
        }
        else if (IsEncodingAccepted(GZIP))
        {
          app.Response.Filter = new GZipStream(app.Response.Filter, CompressionMode.Compress);
          SetEncoding(GZIP);
        }
      }
            else if (app.Context.Request.Path.Contains("WebResource.axd"))
            {
                app.Context.Response.Cache.SetExpires(DateTime.Now.AddDays(30));
            }
    }

/// <summary>
    /// Checks the request headers to see if the specified
    /// encoding is accepted by the client.
    /// </summary>
    private static bool IsEncodingAccepted(string encoding)
    {
      HttpContext context = HttpContext.Current;
      return context.Request.Headers["Accept-encoding"] != null && context.Request.Headers["Accept-encoding"].Contains(encoding);
    }

/// <summary>
    /// Adds the specified encoding to the response headers.
    /// </summary>
    /// <param name="encoding"></param>
    private static void SetEncoding(string encoding)
    {
      HttpContext.Current.Response.AppendHeader("Content-encoding", encoding);
    }

#endregion

}

二:
HttpCompress是在.NET内部通过httpModules模型来实现自定义的压缩模块。

1. 配置
<httpModules>
      <add name="CompressionModule" type="blowery.Web.HttpCompress.HttpModule, blowery.web.HttpCompress"/>
</httpModules>

2.注册事件钩子
context.ReleaseRequestState += new EventHandler(this.CompressContent);
context.PreSendRequestHeaders += new EventHandler(this.CompressContent);
(IHttpModule事件)

3.在代码发送前压缩

void CompressContent(object sender, EventArgs e) ...{
HttpApplication app = (HttpApplication)sender;
      if(!app.Context.Items.Contains(INSTALLED_KEY)) ...{
//设置标志避免重复压缩
        app.Context.Items.Add(INSTALLED_KEY, INSTALLED_TAG);

//设置缓存敏感参数
       app.Response.Cache.VaryByHeaders["Accept-Encoding"] = true;

//根据Accept-Encoding寻找合适的压缩过滤模块CompressingFilter : HttpOutputFilter;
//如果没有设置Accept-Encoding,或者寻找失败均是直接返回,即不压缩
...
CompressingFilter filter = GetFilterForScheme(types, app.Response.Filter, settings);
        if(filter == null)...{
          // if we didn't find a filter, bail out
          return;
        }
        app.Response.Filter = filter;
}
}

4.压缩类实现

HttpOutputFilter ,不支持Read, Seek,GetLength等操作,与之相关控制属性返回false, 具体方法或属性则抛异常new NotSupportedException();

using System;
using System.IO;

namespace blowery.Web.HttpCompress ...{
  /**//// <summary>
  /// The base of anything you want to latch onto the Filter property of a <see cref="System.Web.HttpResponse"/>
  /// object.
  /// </summary>
  /// <remarks>
  /// <p></p>These are generally used with <see cref="HttpModule"/> but you could really use them in
  /// other HttpModules.  This is a general, write-only stream that writes to some underlying stream.  When implementing
  /// a real class, you have to override void Write(byte[], int offset, int count).  Your work will be performed there.
  /// </remarks>
  public abstract class HttpOutputFilter : Stream ...{
    
    private Stream _sink;

    /**//// <summary>
    /// Subclasses need to call this on contruction to setup the underlying stream
    /// </summary>
    /// <param name="baseStream">The stream we're wrapping up in a filter</param>
    protected HttpOutputFilter(Stream baseStream) ...{ 
      _sink = baseStream;
    }

    /**//// <summary>
    /// Allow subclasses access to the underlying stream
    /// </summary>
    protected Stream BaseStream ...{
      get...{ return _sink; }
    }

    /**//// <summary>
    /// False.  These are write-only streams
    /// </summary>
    public override bool CanRead ...{
      get ...{ return false; }
    }

    /**//// <summary>
    /// False.  These are write-only streams
    /// </summary>
    public override bool CanSeek ...{
      get ...{ return false; }
    }

    /**//// <summary>
    /// True.  You can write to the stream.  May change if you call Close or Dispose
    /// </summary>
    public override bool CanWrite ...{
      get ...{ return _sink.CanWrite; }
    }

    /**//// <summary>
    /// Not supported.  Throws an exception saying so.
    /// </summary>
    /// <exception cref="NotSupportedException">Thrown.  Always.</exception>
    public override long Length ...{
      get ...{ throw new NotSupportedException(); }
    }

    /**//// <summary>
    /// Not supported.  Throws an exception saying so.
    /// </summary>
    /// <exception cref="NotSupportedException">Thrown.  Always.</exception>
    public override long Position ...{
      get ...{ throw new NotSupportedException(); }
      set ...{ throw new NotSupportedException(); }
    }

    /**//// <summary>
    /// Not supported.  Throws an exception saying so.
    /// </summary>
    /// <exception cref="NotSupportedException">Thrown.  Always.</exception>
    public override long Seek(long offset, System.IO.SeekOrigin direction) ...{
      throw new NotSupportedException();
    }

    /**//// <summary>
    /// Not supported.  Throws an exception saying so.
    /// </summary>
    /// <exception cref="NotSupportedException">Thrown.  Always.</exception>
    public override void SetLength(long length) ...{
      throw new NotSupportedException();
    }
    
    /**//// <summary>
    /// Closes this Filter and the underlying stream.
    /// </summary>
    /// <remarks>
    /// If you override, call up to this method in your implementation.
    /// </remarks>
    public override void Close() ...{
      _sink.Close();
    }

    /**//// <summary>
    /// Fluses this Filter and the underlying stream.
    /// </summary>
    /// <remarks>
    /// If you override, call up to this method in your implementation.
    /// </remarks>
    public override void Flush() ...{
      _sink.Flush();
    }

    /**//// <summary>
    /// Not supported.
    /// </summary>
    /// <param name="buffer">The buffer to write into.</param>
    /// <param name="offset">The offset on the buffer to write into</param>
    /// <param name="count">The number of bytes to write.  Must be less than buffer.Length</param>
    /// <returns>An int telling you how many bytes were written</returns>
    public override int Read(byte[] buffer, int offset, int count) ...{
      throw new NotSupportedException();
    }

  }
}

CompressingFilter 增加了压缩相关的属性和方法,如,写头

using System;
using System.IO;
using System.Web;

namespace blowery.Web.HttpCompress ...{
  /**//// <summary>
  /// Base for any HttpFilter that performing compression
  /// </summary>
  /// <remarks>
  /// When implementing this class, you need to implement a <see cref="HttpOutputFilter"/>
  /// along with a <see cref="CompressingFilter.ContentEncoding"/>.  The latter corresponds to a 
  /// content coding (see http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.5)
  /// that your implementation will support.
  /// </remarks>
  public abstract class CompressingFilter : HttpOutputFilter ...{

    private bool hasWrittenHeaders = false;

    /**//// <summary>
    /// Protected constructor that sets up the underlying stream we're compressing into
    /// </summary>
    /// <param name="baseStream">The stream we're wrapping up</param>
    /// <param name="compressionLevel">The level of compression to use when compressing the content</param>
    protected CompressingFilter(Stream baseStream, CompressionLevels compressionLevel) : base(baseStream) ...{
      _compressionLevel = compressionLevel;
    }

    /**//// <summary>
    /// The name of the content-encoding that's being implemented
    /// </summary>
    /// <remarks>
    /// See http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.5 for more
    /// details on content codings.
    /// </remarks>
    public abstract string ContentEncoding ...{ get; }

    private CompressionLevels _compressionLevel;

    /**//// <summary>
    /// Allow inheriting classes to get access the the level of compression that should be used
    /// </summary>
    protected CompressionLevels CompressionLevel ...{
      get ...{ return _compressionLevel; }
    }

    /**//// <summary>
    /// Keeps track of whether or not we're written the compression headers
    /// </summary>
    protected bool HasWrittenHeaders ...{ 
      get ...{ return hasWrittenHeaders; } 
    }

    /**//// <summary>
    /// Writes out the compression-related headers.  Subclasses should call this once before writing to the output stream.
    /// </summary>
    protected void WriteHeaders() ...{
      // this is dangerous.  if Response.End is called before the filter is used, directly or indirectly,
      // the content will not pass through the filter.  However, this header will still be appended.  
      // Look for handling cases in PreRequestSendHeaders and Pre
      HttpContext.Current.Response.AppendHeader("Content-Encoding", this.ContentEncoding);
      //HttpContext.Current.Response.AppendHeader("X-Compressed-By", "HttpCompress");
      hasWrittenHeaders = true;
    }


  }
}

执行类,利用压缩类实现了Write,Close,Flush

using System;
using System.IO;

using System.IO.Compression;

namespace blowery.Web.HttpCompress ...{
  /**//// <summary>
  /// Summary description for DeflateFilter.
  /// </summary>
  public class DeflateFilter : CompressingFilter ...{

    /**//// <summary>
    /// compression stream member
    /// has to be a member as we can only have one instance of the
    /// actual filter class
    /// </summary>
    private DeflateStream m_stream = null;

    /**//// <summary>
    /// Basic constructor that uses the Normal compression level
    /// </summary>
    /// <param name="baseStream">The stream to wrap up with the deflate algorithm</param>
    public DeflateFilter(Stream baseStream) : this(baseStream, CompressionLevels.Normal) ...{ }

    /**//// <summary>
    /// Full constructor that allows you to set the wrapped stream and the level of compression
    /// </summary>
    /// <param name="baseStream">The stream to wrap up with the deflate algorithm</param>
    /// <param name="compressionLevel">The level of compression to use</param>
    public DeflateFilter(Stream baseStream, CompressionLevels compressionLevel) : base(baseStream, compressionLevel) ...{
        m_stream = new DeflateStream(baseStream, CompressionMode.Compress);
    }

    /**//// <summary>
    /// Write out bytes to the underlying stream after compressing them using deflate
    /// </summary>
    /// <param name="buffer">The array of bytes to write</param>
    /// <param name="offset">The offset into the supplied buffer to start</param>
    /// <param name="count">The number of bytes to write</param>
    public override void Write(byte[] buffer, int offset, int count) ...{
      if(!HasWrittenHeaders) WriteHeaders();
      m_stream.Write(buffer, offset, count);
    }

    /**//// <summary>
    /// Return the Http name for this encoding.  Here, deflate.
    /// </summary>
    public override string ContentEncoding ...{
      get ...{ return "deflate"; }
    }

    /**//// <summary>
    /// Closes this Filter and calls the base class implementation.
    /// </summary>
    public override void Close() ...{
      m_stream.Close();
    }

    /**//// <summary>
    /// Flushes that the filter out to underlying storage
    /// </summary>
    public override void Flush() ...{
      m_stream.Flush();
    }
  }
}

转载于:https://www.cnblogs.com/shikyoh/archive/2011/04/12/2013502.html

【转】HttpCompress相关推荐

  1. 使用blowery.Web.HttpCompress.dll对aspx压缩

    HttpCompressionModule (HTTP compression for ASP.NET) An IHttpModule for ASP.NET that provides compre ...

  2. ASP.NET页面进行GZIP压缩优化的几款压缩模块的使用简介及应用测试!(附源码)

    在介绍之前,先简单说一说ASP.NET服务端GZIP压缩模块的作用及工作原理,很多人编写网页的时候页面因为使用了大量的JS特效又或者放置很多大型动态广告导致了页面或脚本体积庞大,通常都会使用一些压缩工 ...

  3. http压缩方法(IIS 6.0 与IIS 7.0的详解)

    在网上看了有关这方面的博客,再加上自己的实践,整理了一下,希望对大家有所帮助 本片文章采用两种压缩方法:一种是在IIS上开启GZIP压缩,另一种方法是用CompressionModule压缩模块.下面 ...

  4. 针对ASP.NET页面实时进行GZIP压缩优化的几款压缩模块的使用简介及应用测试!(附源码)...

    在介绍之前,先简单说一说ASP.NET服务端GZIP压缩模块的作用及工作原理,很多人编写网页的时候页面因为使用了大量的JS特效又或者放置很多大型动态广告导致了页面或脚本体积庞大,通常都会使用一些压缩工 ...

  5. 网页地址栏ico图标设置

    关于设置网页地址栏前面的ico小图标方法 <link rel="icon" href="../favicon.ico" type="image/ ...

  6. SQLServer中用户 'sa' 登录失败解决办法

    今天下午,很奇怪的网站突然就打不开了,报错如下: "/"应用程序中的服务器错误.用户 'sa' 登录失败.说明: 执行当前 Web 请求期间,出现未处理的异常.请检查堆栈跟踪信息, ...

  7. Blink SQL之创建数据结果表

    Blink创建数据结果表 概述 Blink使用CREATE TABLE作为输出结果数据的格式定义,同时定义数据如何写入到目的数据结果表. 结果表有两种类型: Append类型:输出存储是日志系统.消息 ...

  8. FluorineFx的配置

    使用"FluorineFx Asp.net Web site"向导生成的项目结构如下: 除了编写.net服务器端代码,Flex客户端代码.还有非常重要的就是正确的设置配置文件.配置 ...

  9. FluorineFX开源库 使用教程(service配置xml说明)

    FluorineFX开源库 使用教程 字体大小: 小 中 大 作者: ddv | 分类: 网站开发 | 浏览: 401 | 评论: 暂时没有评论 转载请保留出处: DDV=敌敌畏 www.dplaye ...

最新文章

  1. 【C++】bind参数绑定 P354(通用的函数适配器)
  2. 如何将mysql数据导入Hadoop之Sqoop安装
  3. SpringMVC通过注解方式读取properties文件中的值
  4. JavaScript继承的多种方式和优缺点
  5. Matlab实用程序--图形应用-填充图
  6. 开源硬件论坛,燃烧你的创造力
  7. 【原】相煎何太急——input的blur事件与button的click事件
  8. android 程序崩溃日记捕捉
  9. 来,一起“八卦”一下数据湖
  10. C和C++实务精选丛书
  11. C# 操作Sqlite
  12. 30岁学编程python_我30岁了,转行学编程可以吗? 排除法告诉你答案
  13. 2013暑假江西联合训练赛 -- by jxust_acm 解题报告
  14. ecshop在nginx下实现负载均衡
  15. 软工网络15团队作业4-DAY2
  16. java调用打印机打印
  17. 笔记本计算机硬盘如何分盘,笔记本电脑怎样分盘_笔记本电脑如何自己分盘-win7之家...
  18. 寒武纪芯片创始人:要让AI芯片计算效率提高一万倍
  19. 在GATE中用ICTCLAS处理多个文档
  20. Docker 网络连通

热门文章

  1. vsftpd虚拟用户
  2. mssql 事务的一个例子
  3. vue 一个组件内多个弹窗_使用vue实现各类弹出框组件
  4. Android 自定义ViewGroup
  5. 500 OOPS: cannot change directory:/home/xxx”
  6. Binary XML file line #6: Error inflating class xxx
  7. Hessian Spring相关使用的简单例子
  8. 使用PostgreSQL进行中文全文检索
  9. JVM篇2:[-加载器ClassLoader-]
  10. SAP是如何与外界沟通的?