クライアントへリクエストのレスポンスを返す場合にサイズが大きいコンテンツを圧縮すると、帯域を効率的に使用できます。IISを使用すると静的コンテンツの圧縮を行えます。IIS5.0,6.0の場合、ASP.NETのaspxファイルでも下記のリンクを参考にすれば、コンテンツを圧縮してクライアントにレスポンスを行えるようになります。今回はIHttpModuleを実装し、モジュールクラスでgzip, deflate 形式の圧縮を行ってレスポンスを返すことができるようにしてみます。

[HOW TO] ASPX 圧縮 IIS で有効にします。
http://support.microsoft.com/kb/322603/ja
HOW TO: Enable ASPX Compression in IIS
http://support.microsoft.com/kb/322603/en

確認環境

  • サーバー:Visual Studio 2008 Professionalの組み込みサーバ,Windows Server 2003 Enterprise R2
  • クライアント:IE7.0, IE6.0
  • 開発環境:Visual Studio 2008 Professional 英語版
  • .NET 3.5(.NET 2.0以上で動作するはずです)

1. ConmpressionModuleの作成

Webサイトプロジェクトを新規作成し、App_Codeフォルダにファイルを新規作成します。名前をCompressionModule.csとします。プロジェクトはWeb Application Projectでも問題ありませんが、ここではWeb サイト プロジェクトとして記載をします。Web Application Projectの場合でApp_Codeフォルダにファイルを作成した場合は、プロパティでビルドアクションをCompileにすることを忘れないで下さい。

作成したCompressionModuleを次のように編集します。

using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.IO.Compression;

namespace ComponentGeek.Web.UI
{
    public class CompressionModule : IHttpModule
    {
        #region IHttpModule Members

        public void Dispose()
        {
            //throw new NotImplementedException();
        }

        public void Init(HttpApplication context)
        {
            context.BeginRequest += new EventHandler(context_BeginRequest);
        }

        void context_BeginRequest(object sender, EventArgs e)
        {
            HttpApplication application = sender as HttpApplication;
            HttpContext context = application.Context;

            //if (!application.Request.Path.EndsWith(".aspx")) return;
            string encoding = application.Request.Headers.Get("Accept-Encoding");
            if (encoding == null) return;

            if (encoding.Contains("gzip"))
            {
                application.Response.Filter = new GZipStream(application.Response.Filter, CompressionMode.Compress);
                application.Response.AppendHeader("Content-Encoding", "gzip");
            }
            else if (encoding.Contains("deflate"))
            {
                application.Response.Filter = new DeflateStream(application.Response.Filter, CompressionMode.Compress);
                application.Response.AppendHeader("Content-Encoding", "deflate");
            }
        }

        #endregion
    }
}

処理は簡単で、WebResponse.FilterプロパティにGZipStreamもしくは、DeflateStreamを設定しているだけです。ブラウザに圧縮されていることを知らせるためにContent-Encodingヘッダにコンテンツの圧縮形式を設定するようにしています。あとは、web.configに登録して準備完了です。system.webセクション内にhttpModulesセクションがなければ追加し、作成したCompressionModuleを登録します。

<httpModules>
  <!-- 省略  -->
  <add name="CompressModule" type="ComponentGeek.Web.UI.CompressionModule"/>
</httpModules>

以上で設定完了です。Fiddler2などのhttp通信をモニタするツールで確認すると、データが圧縮されていることやデータサイズが減少していることを確認できます。

IEが圧縮されたコンテンツをうまく取り扱えない場合があるので注意して下さい。

"Content-Encoding: gzip" を指定したコンテンツが "Cache-Control: no-cache" を使用しても常にキャッシュされる
http://support.microsoft.com/kb/321722/ja
GZIP データ圧縮方式で圧縮されたデータが Internet Explorer で正常に展開されない
http://support.microsoft.com/kb/837251/ja

圧縮を有効にする場合の注意点

今回のサンプルでは無条件でデータの圧縮を行っていますが、他のツールを使用している場合に不具合の元になる可能性があるので注意して下さい。例えば、本サイトで内部的に使用しているFCKEditorというツールがあるのですが、すべてのaspxファイルを圧縮するようにすると、FCKEditorのファイルブラウザは動作しなくなります。

今回の説明は以上です。指摘点、誤り等があればご連絡ください。