20

我一直在为我的 MVC 操作使用压缩过滤器,如下所述:

http://msdn.microsoft.com/en-us/magazine/gg232768.aspx

我试图重新利用代码为 Web API 做类似的事情,但我遇到了一个障碍:

public class CompressAPIAttribute : System.Web.Http.Filters.ActionFilterAttribute
{
    public override void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext filterContext)
    {
        var preferredEncoding = GetPreferredEncoding(filterContext.Request);
        Stream compressedStream = null;
        // Compress the response accordingly
        var response = filterContext.Response;
        response.Headers.Add("Content-encoding", preferredEncoding.ToString());

        if (preferredEncoding == CompressionScheme.Gzip)
        {
            response.Content = new GZipStream(compressedStream, CompressionMode.Compress); //THIS WON'T WORK
        } 

        if (preferredEncoding == CompressionScheme.Deflate)
        {
            response.Content = new DeflateStream(compressedStream, CompressionMode.Compress); //THIS WON'T WORK
        }
        return;
    }

    enum CompressionScheme
    {
        Gzip = 0,
        Deflate = 1,
        Identity = 2
    }

    private CompressionScheme GetPreferredEncoding(HttpRequestMessage request)
    {
        var acceptableEncoding = request.Headers.AcceptEncoding;

        if (acceptableEncoding.Where(h => h.Value.Contains("gzip")).Count() > 0)
            return CompressionScheme.Gzip;

        if (acceptableEncoding.Where(h => h.Value.Contains("deflate")).Count() > 0)
            return CompressionScheme.Deflate;

        return CompressionScheme.Identity;
    }

有什么想法可以将压缩流分配给响应的内容吗?

我应该指出这是托管在我无法控制的 IIS 6.0 中。

4

2 回答 2

60

我认为您不应该操作过滤器中执行此操作,因为模型绑定阶段发生在操作过滤器执行之前,并且在模型绑定期间,格式化程序可能正在读取流以对其进行反序列化,在这种情况下它将失败。

如果您使用的是 IIS,请执行以下操作来设置压缩(以下是 Scott Hanselman博客文章中的一些片段):

  • 在 IIS 中启用“动态压缩”功能。

  • 回到 IIS 管理器,转到SERVER页面,而不是 SITE 页面。点击配置编辑器: 在此处输入图像描述

  • 从下拉列表中选择 system.webServer/httpCompression: 在此处输入图像描述

  • 然后单击动态类型,现在您在列表编辑器中,请考虑要压缩的类型。默认情况下/是 False,但你可以打开它。我选择更挑剔一些,并添加了 application/atom+xml、application/json 和 application/atom+xml;charset=utf-8,如下所示。application/atom+xml 和 application/atom+xml;charset=utf-8 是单独的条目,这有点麻烦。随意在此处添加您喜欢的任何 mimeTypes。 在此处输入图像描述
  • 添加它们并关闭对话框后,请务必单击应用重新启动IIS 服务以加载新模块。
  • 现在使用Accept-Encoding标头发出请求,您应该会看到预期的响应。

  • 编辑(除上述内容外,还包括“application/json; charset=utf-8”以涵盖两种 json 格式)

于 2013-06-26T22:34:59.433 回答
1

如果您使用 IIS 设置压缩,您可以修改文件:

C:\Windows\System32\inetsrv\config\applicationHost.config

添加以下标签

    <dynamicTypes>
        <add mimeType="text/*" enabled="true" />
        <add mimeType="message/*" enabled="true" />
        <add mimeType="application/x-javascript" enabled="true" />
        <add mimeType="application/atom+xml" enabled="true" />
        <add mimeType="application/atom+xml; charset=utf-8" enabled="true" />
        <add mimeType="application/json" enabled="true" />
        <add mimeType="application/json; charset=utf-8" enabled="true" />
        <!--<add mimeType="application/*" enabled="true" />-->
        <add mimeType="*/*" enabled="false" />
        <staticTypes>
        ...
        </staticTypes>
    </dynamicTypes>

在该部分:

<httpCompression directory="%SystemDrive%\inetpub\temp\IIS Temporary Compressed Files">
    <scheme name="gzip" dll="%Windir%\system32\inetsrv\gzip.dll" />
        <!-- 
            add here 
        -->
        <staticTypes>
            <add mimeType="text/*" enabled="true" />
            <add mimeType="message/*" enabled="true" />
            <add mimeType="application/x-javascript" enabled="true" />
            <add mimeType="application/atom+xml" enabled="true" />
            <add mimeType="application/xaml+xml" enabled="true" />
            <add mimeType="*/*" enabled="false" />
        </staticTypes>
</httpCompression>

添加它们后,重新启动IIS 服务以加载新模块。

可以通过修改标签来提高压缩级别:

<scheme name="gzip" dll="%Windir%\system32\inetsrv\gzip.dll"
 staticCompressionLevel="9" dynamicCompressionLevel="9" />

完毕 :)

PS:记得在 IIS 服务器的配置编辑器中的路径 system.webServer/httpCompression 下启用动态压缩

于 2018-05-20T14:43:29.023 回答