IIS启用GZip压缩后带来的问题及解决办法

页面文件比较大时,开启GZip压缩可以减少传输的流量,测试了一下效果非常明显,看了园子里面有些人使用了IIS的GZip压缩功能,项目中也应用了该功能,使用的过程中遇到一个比较棘手的问题,找了挺久的一直搞不定。
     项目中在服务器端生成了Excel2007报表文件,文件在下载到本地后不能正常打开了,提示文件格式有问题,由于Excel2007文件格式的本质是一压缩包,怀疑文件在下载的过程中被改动了,但是具体不知道在哪个环节上出了问题。
这里是我发的一个博问,知道的帮下忙啊。
 
      猜想:
     1.因为Excel2007文件是在页面Render的时候输出的,并且输出完后直接End请求,可以推断IIS的压缩机制,应该是在请求开始的时候就已经加入,而不是在请求结束的时候进行压缩的。
     2.文件下载时直接弹出下载框进行下载,可能没有经过浏览器的解压过程。这一点有待考证。抑或有其他原因导致了不能对压缩包进行加压,因为这个压缩包是经过两次打包过的(Excel2007文件生成的时候打包过一次,在通过IIS下载时又被打包了一次)。
 
      使用IIS压缩的问题(目前发现的):
     1.配置不方便,要更改系统里面的那个配置文件,权限不够的话没办法配置。
     2.IIS6下会影响到IIS内的所有站点,据说IIS7不存在这个问题。
     3.配置了IIS压缩的机器,在重启几次后配置丢失了(怪事)。
     4.Excel2007下载的问题,估计OOXML格式的问题都会有问题。
 
      解决:
     解决的办法就是使用HttpModule进行压缩,在HttpModule中使用PostReleaseRequestState事件进行压缩,将压缩的时机延后到Render之后,通常的代码都不会卸载Render之后了吧 :)
     既然PostReleaseRequestState事件是在Render之后,有人会有疑问了,那也可以在页面里面订阅啊,在我实际的测试中发现是不能在页面逻辑中改变Response.Filter,会报错的,这个可能涉及到asp.net中的一些权限吧,所以还是老老实实的在HttpModule中去实现吧。
ContractedBlock.gif ExpandedBlockStart.gif CompressModule
using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
using System.IO;
using System.IO.Compression;

namespace CapabilityTest
{
    
public class CompressModule : IHttpModule
    {
        
#region IHttpModule Members

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

        
public void Init(HttpApplication context)
        {
            context.PostReleaseRequestState 
+= new EventHandler(context_PostReleaseRequestState);
        }

        
#endregion

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

        
private void context_PostReleaseRequestState(object sender, EventArgs e)
        {
            HttpApplication app 
= sender as HttpApplication;
            Stream filter 
= app.Response.Filter;

            
if (IsEncodingAccepted(app.Request, GZIP))
            {
                app.Response.Filter 
= new GZipStream(filter, CompressionMode.Compress);
                app.Response.AppendHeader(
"Content-Encoding", GZIP);
            }
            
else if (IsEncodingAccepted(app.Request, DEFLATE))
            {
                app.Response.Filter 
= new DeflateStream(filter, CompressionMode.Compress);
                app.Response.AppendHeader(
"Content-Encoding", DEFLATE);
            }
        }

        
private static bool IsEncodingAccepted(HttpRequest request, string encoding)
        {
            
string acceptEncoding = request.Headers["Accept-Encoding"];
            
if (acceptEncoding == null)
                
return false;

            acceptEncoding 
= acceptEncoding.ToLower();
            
if (encoding == GZIP)
                
return acceptEncoding.Contains(GZIP) || acceptEncoding.Contains("x-gzip"|| acceptEncoding.Contains("*");

            
if (encoding == DEFLATE)
                
return acceptEncoding.Contains(DEFLATE);

            
return false;
        }
    }
}
 
      改进:
     1.可以在config文件中加入自定义的ConfigurationSection,使用配置的方式实现对指定的文件扩展名进行压缩,或排除对指定的文件扩展名的压缩。
     2.网络上看到有人说要针对微软的AJAX做处理,不能进行压缩,判断的方法:
          return (app.Request["HTTP_X_MICROSOFTAJAX"] != null
                  || app.Request["Anthem_CallBack"] != null);
     3.可针对实现了某个基类或接口的页面进行压缩或不压缩:
           ICompressable p = app.Context.Handler as ICompressable;
           return (p == null);
 
      此外:
     本文针对IIS6,最新的IIS7没有亲身体验过,不知道关于压缩方面做得好不好。文中提到的PostReleaseRequestState事件只有在asp.net 2.x才开始支持,故不能用于vs2003开发的项目哦。
 
      完整代码下载
 
Tag标签: GZip, IIS压缩, HttpModule
0
0
0
(请您对文章做出评价)

Feedback

#1楼   回复  引用  查看    

2009-02-19 16:45 by Goodspeed       
还是IIS7比较爽,配置一下就行啦。

#2楼[楼主]   回复  引用  查看    

2009-02-19 23:08 by ppchen(陈荣林)       
@Goodspeed
没用过IIS7哦,找个时间去体验一下

#3楼 85.19.68.*   回复  引用    

2009-05-05 01:19 by 刘涛[未注册用户]
谢谢分享,很有用

#4楼 219.232.59.*   回复  引用    

2009-05-13 11:32 by jisen007[未注册用户]
感觉挺好,不过我在测试的时候发现一个问题,只能压缩aspx,js和css文件都不能压缩,我跟踪了一下,压缩代码执行了,但是没有压缩效果,为什么?

#5楼[楼主]   回复  引用  查看    

2009-05-17 19:53 by ppchen(陈荣林)       
@jisen007
我做了在web.comfig的配置,可能是那边没配置好


转自:http://www.cnblogs.com/ppchen/archive/2009/02/19/1382530.html

转载于:https://www.cnblogs.com/qiantuwuliang/archive/2009/08/08/1542009.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值