设为首页 收藏本站
查看: 969|回复: 0

[经验分享] IIS启用GZip压缩后带来的问题及解决办法

[复制链接]
累计签到:1 天
连续签到:1 天
发表于 2015-8-12 13:44:59 | 显示全部楼层 |阅读模式
  页面文件比较大时,开启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中去实现吧。

DSC0000.gif DSC0001.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开发的项目哦。

     完整代码下载

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-97993-1-1.html 上篇帖子: Silverlight4学习笔记2--WCF的IIS发布 下篇帖子: 打卡IIS的快捷键
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表