如何在ASP.NET中实现GZip压缩?

83

我正在尝试为我的asp.net页面(包括CSS和JS文件)实现GZip压缩。我尝试了以下代码,但它只压缩了我的.aspx页面(从YSlow发现的)。

HttpContext context = HttpContext.Current;
context.Response.Filter = new GZipStream(context.Response.Filter, CompressionMode.Compress);
HttpContext.Current.Response.AppendHeader("Content-encoding", "gzip");
HttpContext.Current.Response.Cache.VaryByHeaders["Accept-encoding"] = true;

以上代码仅压缩我的.aspx页面代码(标记),而不是包含为外部文件的CSS和JS文件。 请告诉我如何使用代码在ASP.NET中实现GZip压缩(因为我在共享托管服务器上,无法访问IIS服务器配置)。此外,在上面的代码中,我没有理解最后两行,它们的用途是什么。请解释一下!


不完全是重复的:https://dev59.com/lWw05IYBdhLWcg3w11W0 - jpaugh
9个回答

49

以下是CSS和JavaScript文件的解决方案。将以下代码添加到Web.config文件中<system.webServer>标签内:

<configuration>
  ...
  <system.webserver>
     ...
      <httpCompression>
        <scheme name="gzip" dll="%Windir%\system32\inetsrv\gzip.dll"/>
        <dynamicTypes>
          <add mimeType="text/*" enabled="true"/>
          <add mimeType="message/*" enabled="true"/>
          <add mimeType="application/javascript" enabled="true"/>
          <add mimeType="*/*" enabled="false"/>
        </dynamicTypes>
        <staticTypes>
          <add mimeType="text/*" enabled="true"/>
          <add mimeType="message/*" enabled="true"/>
          <add mimeType="application/javascript" enabled="true"/>
          <add mimeType="*/*" enabled="false"/>
        </staticTypes>
      </httpCompression>
      <urlCompression doStaticCompression="true" doDynamicCompression="true"/>
    ...
  </system.webserver>
  ...
<configuration>

引用: 如何在ASP.NET和GoDaddy上使用GZip


4
最后一行应该被删除。 - JeffT
1
是的,但我实际上会添加开头的<system.webServer>...这样我们就知道在哪里放置配置。 - Carlos R Balebona
我添加了相同的代码,但文件没有被压缩。 - Zeeshan Ahmad Khalil
我需要添加其他内容吗? - Zeeshan Ahmad Khalil

29

压缩JS和CSS文件需要在IIS层面处理,因为这些文件是直接呈现的,不经过ASP.NET运行时。

你可以在IIS中创建JSX和CSSX扩展映射到aspnet_isapi.dll,然后利用你的zip代码,但是IIS很可能会更好地为你完成这项工作。

content-encoding头告诉浏览器在呈现内容之前需要解压内容。有些浏览器可以根据内容的形状自动判断,但最好还是明确告知它。

Accept-encoding缓存设置是为了避免将已经压缩过的缓存版本发送给只请求text/html的浏览器。


4
嗨@Ben,你能告诉我如何使用IIS压缩我的文件吗?有哪些设置我需要执行?虽然我没有访问IIS配置的权限,但我会尝试去实现。请告诉我如何使用IIS压缩文件?谢谢! - djmzfKnm
4
https://dev59.com/lWw05IYBdhLWcg3w11W0#6992948详细介绍了在IIS7或更高版本中所需的web.config简单更改。 - Rory

17

这对你可能有用,试一下吧,它支持 deflate 和 gzip 压缩。

    void Application_PreRequestHandlerExecute(object sender, EventArgs e)
    {
        HttpApplication app = sender as HttpApplication;
        string acceptEncoding = app.Request.Headers["Accept-Encoding"];
        Stream prevUncompressedStream = app.Response.Filter;

        if (app.Context.CurrentHandler == null)
            return;

        if (!(app.Context.CurrentHandler is System.Web.UI.Page ||
            app.Context.CurrentHandler.GetType().Name == "SyncSessionlessHandler") ||
            app.Request["HTTP_X_MICROSOFTAJAX"] != null)
            return;

        if (acceptEncoding == null || acceptEncoding.Length == 0)
            return;

        acceptEncoding = acceptEncoding.ToLower();

        if (acceptEncoding.Contains("deflate") || acceptEncoding == "*")
        {
            // deflate
            app.Response.Filter = new DeflateStream(prevUncompressedStream,
                CompressionMode.Compress);
            app.Response.AppendHeader("Content-Encoding", "deflate");
        }
        else if (acceptEncoding.Contains("gzip"))
        {
            // gzip
            app.Response.Filter = new GZipStream(prevUncompressedStream,
                CompressionMode.Compress);
            app.Response.AppendHeader("Content-Encoding", "gzip");
        }
    } 

2
非常感谢您提供的代码。我需要对一个我无法访问IIS控制台的特定网站进行gzip/deflate压缩,这个代码帮了我大忙。不过我有一个问题:这个代码似乎对所有的aspx文件进行了deflate压缩,并且对CSS和ScriptResources进行了gzip压缩,但是它没有对任何.js文件进行gzip压缩。有什么方法可以解决这个问题吗?谢谢。 - Rafael Merlin
这是错误的,因为您没有像这样处理质量指令:gzip;q=0,deflate。http://www.singular.co.nz/2008/07/finding-preferred-accept-encoding-header-in-csharp/ - oligofren

11

你的ASPX文件只被压缩的原因是,你所编写的代码仅嵌入了ASPX文件中。ASPX文件是与其包含的任何链接内容分开请求的。因此,如果你有一个包含以下内容的ASPX页面:

<img src="www.example.com\exampleimg.jpg" alt="example" />
这将涉及浏览器向资源发出2个请求(除DNS查找外):
1. 获取aspx页面 2. 获取aspx页面包含的图像
每个请求都有自己的响应流。您发布的代码仅附加到ASPX响应流,这就是为什么仅压缩了ASPX页面的原因。您发布的代码的第1和第2行基本上接管了页面的正常响应流,并注入了一些“中间代码”,在这种情况下使用GZip流吃掉并压缩正常的输出流,并将其发送到线路上。
第3和第4行设置响应头。所有http请求和响应都具有在内容之前发送的标头。这些设置请求/响应,以便服务器和客户端知道正在发送什么以及如何发送。
在这种情况下,第3行通知客户端浏览器响应流通过gzip压缩,因此需要在显示之前由客户端浏览器进行解压缩。
第4行只是打开响应的Accept-Encoding头。否则,它将缺少响应。
您可以编写/获取可插入模块,允许您压缩多个其他MIME类型,例如*.js和*.css,但最好只使用IIS的内置压缩功能。
您没有说您使用的是哪个版本的IIS,但如果是IIS 7.0,则需要将以下内容包含在web.config文件的部分中:
<httpCompression> 
  <scheme name="gzip" dll="%Windir%\system32\inetsrv\gzip.dll" /> 
 <staticTypes>
         <add mimeType="text/*" enabled="true" />
      </staticTypes>
</httpCompression> 
<urlCompression doStaticCompression="true" /> 

Richard


真的很棒的描述 - rakeshyadvanshi

3
在IIS7中,所有请求都会进入.net,因此您需要创建一个HttpModule,将这些标头添加到所有响应中。
如果没有使用IIS7,并且在共享托管上,您需要创建一个处理程序,将您未使用的.NET文件扩展名(如.asmx)映射为web.config指定的.asm文件,然后将.asm文件发送到您的HttpHandler,该处理程序设置为将路径重写为.jpg或其他内容,并在那里设置标头。

2
回答你的最后一个问题。这两行代码设置了发送回浏览器的响应的HTTP头信息。Content-Encoding告诉浏览器响应被gzip编码,并需要解码。最后一行将Accept-Encoding添加到Vary header中。这样,浏览器或代理可以确定响应是唯一的还是受某些其他头信息的影响,并调整它们的缓存。

0

您可以在<system.webServer>元素内的web.config文件中添加以下内容:

<urlCompression doStaticCompression="true" doDynamicCompression="true" />

注意:如果您使用的是旧版 IIS(低于 v7.5),则可能希望将 doDynamicCompression 设置为 false,因为该过程会消耗 CPU。这些问题已在 IIS 7.5 中得到解决。

参考资料:https://learn.microsoft.com/en-us/iis/configuration/system.webserver/urlcompression


0
将 .aspx 扩展名添加到 .css 或 .js 文件中。在文件内使用 <%@ Page ContentType="text/css" %> 或 javascript 以正确的 MIME 类型提供服务。并使用 URL Rewrite 隐藏此内容,使用户代理浏览器无法看到。content-encoding 响应头附加 gzip,以传达 gzip 是用于执行压缩的方法。Vary 响应头设置为 Accept-Encoding,以便所有缓存都知道哪个页面(压缩或未压缩)应该根据请求的 Accept-Encoding 标头提供服务。我已经在 https://stackoverflow.com/a/14509007/1624169 上详细说明了这一点。

0

可以通过 web.config 文件来完成。

<system.webServer>
    <httpCompression>
        <scheme name="gzip" dll="%Windir%\system32\inetsrv\gzip.dll"/>
        <dynamicTypes>
            <add mimeType="text/*" enabled="true"/>
            <add mimeType="message/*" enabled="true"/>
            <add mimeType="application/javascript" enabled="true"/>
            <add mimeType="*/*" enabled="false"/>
        </dynamicTypes>
        <staticTypes>
            <add mimeType="text/*" enabled="true"/>
            <add mimeType="message/*" enabled="true"/>
            <add mimeType="application/javascript" enabled="true"/>
            <add mimeType="*/*" enabled="false"/>
        </staticTypes>
    </httpCompression>
    <urlCompression doStaticCompression="true" doDynamicCompression="true"/>
</system.webServer>

或者您可以通过IIS来完成。对于压缩JS和CSS文件,您实际上需要在IIS层面处理,因为这些文件是直接呈现而不需要ASP.NET运行时。

您可以在IIS中创建JSX和CSSX扩展映射到aspnet_isapi.dll,然后利用您的zip代码,但是IIS很可能会更好地为您完成此任务。

内容编码标头告诉浏览器它需要在呈现之前解压内容。一些浏览器已经足够聪明,根据内容的形状自动判断,但最好还是将其明确告知。

Accept-encoding 缓存设置是为了使仅请求text/html的浏览器不获取已被缓存的gzipped内容版本。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接