Windows XP Windows 7 Windows 2003 Windows Vista Windows 綜合教學 Linux 系統教學
Windows 10 Windows 8 Windows 2008 Windows NT Windows Server 電腦軟體教學
您现在的位置: Windows教程網 >> Windows教程 >  >> 電腦軟體教學 >> 伺服器技術 >> 關於伺服器

IIS 6 Gzip 壓縮導致 Excel 2007 (OOXML) 下載損壞?HttpModule 延後壓縮完美解決

編輯:關於伺服器

問題現象

啟用 IIS 6 原生 Gzip 後,伺服器端產生的 .xlsx (Excel 2007) 檔案下載至用戶端無法開啟,提示格式錯誤。根因:OOXML 本質為 ZIP 封裝,經 IIS 二次壓縮導致雙重壓縮,瀏覽器未正確解壓即存檔。

推測與驗證

  1. IIS 壓縮在 Request 早期介入,Render 階段輸出的二進位檔案流被再次壓縮。
  2. 瀏覽器下載時未觸發解壓邏輯 (缺少 Content-Encoding: gzip 標頭或 MIME 類型不匹配)。

IIS 原生壓縮的缺點

  • 需修改 MetaBase.xml,權限門檻高。
  • 影響該 IIS 所有站點 (IIS 7 已改善)。
  • 重啟後設定遺失風險。
  • 對已壓縮格式 (OOXML、JPG、PNG、ZIP) 造成雙重壓縮損壞。

解決方案:自訂 HttpModule 在 PostReleaseRequestState 壓縮

於 PostReleaseRequestState 事件 (Render 完成、Response 尚未發送) 動態包裝 Response.Filter,僅壓縮文字類內容 (HTML、CSS、JS、JSON),排除二進位檔案。

public class CompressModule : IHttpModule {
  public void Init(HttpApplication context) {
    context.PostReleaseRequestState += OnPostReleaseRequestState;
  }
  private void OnPostReleaseRequestState(object sender, EventArgs e) {
    var app = (HttpApplication)sender;
    var accept = app.Request.Headers["Accept-Encoding"]?.ToLower();
    if (string.IsNullOrEmpty(accept)) return;

    Stream filter = app.Response.Filter;
    if (accept.Contains("gzip") || accept.Contains("x-gzip") || accept.Contains("*")) {
      app.Response.Filter = new GZipStream(filter, CompressionMode.Compress);
      app.Response.AppendHeader("Content-Encoding", "gzip");
    } else if (accept.Contains("deflate")) {
      app.Response.Filter = new DeflateStream(filter, CompressionMode.Compress);
      app.Response.AppendHeader("Content-Encoding", "deflate");
    }
  }
  public void Dispose() { }
}

進階改良建議

  1. 白/黑名單機制:在 web.config 定義 <compressionExtensions>,排除 .xlsx, .zip, .jpg 等。
  2. ASP.NET AJAX 相容:偵測 HTTP_X_MICROSOFTAJAX 或 Anthem_CallBack 標頭,略過壓縮避免 UpdatePanel 異常。
  3. 頁面層級控制:實作 ICompressible 介面,僅壓縮標記頁面。

適用範圍與注意

  • 需 ASP.NET 2.0+ (含 PostReleaseRequestState 事件)。
  • IIS 7/7.5/8/10 建議改用原生 <urlCompression> + <dynamicCompression> 設定,支援模組化、不影響全站。
Copyright © Windows教程網 All Rights Reserved