当前位置: 电脑软硬件应用网 > 电脑学院 > 服务器技术 > 正文 |
|
|||
IIS启用GZip压缩后带来的问题及解决办法 | |||
2010-1-1 9:04:56 文/陈荣林 出处:电脑软硬件应用网 | |||
项目中在服务器端生成了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中去实现吧。
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开发的项目哦。
|
|||
关于45IT | About 45IT | 联系方式 | 版权声明 | 网站导航 | |
Copyright © 2003-2011 45IT. All Rights Reserved 浙ICP备09049068号 |