Web API 的压缩过滤器

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上托管的,而我无法控制它。

2
在ASP.NET Web API中,更好的方法是使用“DelegatingHandler”,并且已经有一个回答描述了解决方案https://dev59.com/pmkv5IYBdhLWcg3wqSf1。 - tpeczek
一个过滤器允许您仅指定某些WebAPI操作...但是委托处理程序是否强制压缩所有操作? - Simon Green
2个回答

65

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

如果您正在使用IIS,则可以按照以下步骤设置压缩(以下内容包含Scott Hanselman的博客文章中的一些片段):

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

  • 回到IIS管理器,转到服务器页面,而不是站点。单击“配置编辑器”: enter image description here

  • 从下拉列表中选择system.webServer/httpCompression: enter image description here

  • 然后单击动态类型,现在您在列表编辑器中,请考虑要压缩哪些类型。默认情况下,/为False,但您可以打开它。我选择更加挑剔,添加了application/atom+xml、application/json和application/atom+xml;charset=utf-8,如下所示。这是一个小陷阱,application/atom+xml和application/atom+xml;charset=utf-8是单独的条目。随意添加您喜欢的MIME类型。 enter image description here
  • 在添加它们并关闭对话框后,请务必单击应用重启您的IIS服务以加载新模块。
  • 现在使用Accept-Encoding头进行请求,您应该看到预期的响应。

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


1
好东西!不幸的是,我使用的是没有服务器控制权的IIS 6.0。 - Mister Epic
1
注意:如果您没有配置编辑器(例如我在IIS 7中),只需从WebInstaller安装管理包。 - Kugel
2
这对我来说是有效的,但我不确定设置存储在哪里。MMC snapin 的底部显示配置:ApplicationHost.config。我无法在 C:\Windows\System32\inetsrv\config\applicationhost.config 中看到这些设置。(这是我之前尝试编辑的文件)。而且我在我的服务器上找不到任何其他修改过的 applicationhost.config 文件?(Windows 2012) - Tim
1
@Tim,你找到设置了吗?我也遇到了同样的问题...一切都正常,但不知道它存储在哪里。 - jazzcat
3
@Tim 更新:我找到了。你可能正使用像Notepad++这样的32位程序查看文件。请改用Windows默认的64位记事本,它将显示实际的文件(因为notepad++被重定向到SysWOW64文件夹,因为它是32位的)。 - jazzcat
显示剩余3条评论

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服务器的Configuration Editor中启用路径system.webServer/httpCompression下的动态压缩


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