Saturday, 19 July 2008

Adding simple Gzip compression for a 40-60% reduction in page size on your ASP.NET 2.0 Site

UPDATE (29 October 2008): If you can, try to use the following:
http://www.codeproject.com/KB/aspnet/httpcompression.aspx
This has a some major benefits such as compressing your axd files, combining your css and javascript and minifying the output.

There are a few different ways to get Gzip compression happening on your site. These include:

  1. Custom Http modules that implement IHttpModule such as http://blowery.org/httpcompress/

  2. 3rd party handlers such as http://www.port80software.com/products/httpzip/

  3. If you have full access to the IIS Box and metabase, use the built-in Gzip compression available in IIS 6.0 and above (See http://weblogs.asp.net/owscott/archive/2004/01/12/57916.aspx for more information)

  4. Modifying the global.asax to implement compression.
I briefly outline option 4 below. With ASP.NET, it is incredibly easy to get it up and running without any additonal server set up. Note that it is important that you don't gzip your axd files through this code. Some UI components such as Telerik RadControls will generate several javascript errors if you try to gzip its axd resource files. I also found that a page I created for dynamically rendering images started chop images off at the bottom. So I excluded them from any attempts at compression.

If you look at your page size in YSLow, it will typically be reduced by 40-60%. e.g. from 200K to 100K.

Here's some sample code that you can put into your global.asax with minor modifications appropriate to your project:




  //Gzip support

    void Application_BeginRequest(object sender, EventArgs e)

    {

        HttpApplication app = (HttpApplication)sender;

        if (app.Request.Url.ToString().Contains("ImageGenerator.aspx")  app.Request.Url.ToString().Contains("WebResource.axd")  app.Request.Url.ToString().Contains("ScriptResource.axd")) //Dont process this as it corrupts images/scripts

            return;

        string acceptEncoding = app.Request.Headers["Accept-Encoding"];

        Stream prevUncompressedStream = app.Response.Filter;

 

        if (acceptEncoding == null  acceptEncoding.Length == 0)

            return;

 

        acceptEncoding = acceptEncoding.ToLower();

 

        if (acceptEncoding.Contains("gzip"))

        {

            // gzip

            app.Response.Filter = new GZipStream(prevUncompressedStream,

                CompressionMode.Compress);

            app.Response.AppendHeader("Content-Encoding",

                "gzip");

        }

        else if (acceptEncoding.Contains("deflate"))

        {

            // deflate

            app.Response.Filter = new DeflateStream(prevUncompressedStream,

                CompressionMode.Compress);

            app.Response.AppendHeader("Content-Encoding",

                "deflate");

        }

    }
 
 
 


For more information on IIS and the built-in settings when you have full access to IIS, see the following articles for reference:

http://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/d52ff289-94d3-4085-bc4e-24eb4f312e0e.mspx?mfr=true
http://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/502ef631-3695-4616-b268-cbe7cf1351ce.mspx?mfr=true


The IIS compression dialog:





2 comments:

David Klein said...

Updated with additional info from Donald Chow (Lend Lease) RE: IIS 6+ Compression

Anonymous said...

users of this will need to include
the following namespaces
using System.IO;
using System.IO.Compression;

another version of this article is available at http://www.stardeveloper.com/articles/display.html?article=2007110401&page=1

By the way your kids are so cute, you should generate another instance!