Windows XP Windows 7 Windows 2003 Windows Vista Windows教程綜合 Linux 系統教程
Windows 10 Windows 8 Windows 2008 Windows NT Windows Server 電腦軟件教程
 Windows教程網 >> 電腦軟件教程 >> 服務器技術 >> 關於服務器 >> IIS啟用GZip壓縮後帶來的問題及解決辦法

IIS啟用GZip壓縮後帶來的問題及解決辦法

日期:2017/2/8 10:26:39      編輯:關於服務器
    頁面文件比較大時,開啟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中去實現吧。 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開發的項目哦。
Copyright © Windows教程網 All Rights Reserved