我如何缓存和压缩响应?

时间:2012-07-27 14:14:41

标签: asp.net asp.net-mvc-3 caching compression

我的一些回复,包括GET个网页和POST回复,都会在短时间内实施[OutputCache]

我还使用以下功能启用了站点范围的压缩:

protected void Application_BeginRequest(object sender, EventArgs e)
{
    // Implement HTTP compression
    var app = (HttpApplication) sender;

    // Retrieve accepted encodings
    var encodings = app.Request.Headers.Get("Accept-Encoding");
    if (encodings == null)
        return;
    encodings = encodings.ToLower();

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

问题是它试图重新压缩缓存的文件。这意味着每当我发送缓存响应时,它都会被压缩成垃圾。

我考虑过尝试查看app.Response.Headers["Content-Encoding"]现有压缩,但我得到PlatformNotSupported例外。如何在不删除缓存响应的情况下启用压缩?

1 个答案:

答案 0 :(得分:0)

对于初学者,我会将该逻辑移动到Application_PostRequestHandlerExecute,只有在页面实际执行时才会执行。在这种情况下,压缩输出和Content-Encoding标头将被缓存并作为响应发送。随后的缓存命中将提供压缩内容和标题,而不进行过滤器分配。

其次,你要让缓存知道这个URL因内容编码而异。你需要在那里添加这一行(在短路之前):

app.Response.Cache.SetVaryByCustom("encoding");

以及覆盖HttpApplication.GetVaryByCustomString,以及:

protected override GetVaryByCustomString(HttpContext ctx, string custom) {
    if (custom != "encoding") return base.GetVaryByCustomString(ctx, custom);

    var acceptEncodings = ctx.Request.Headers["Accept-Encoding"];
    if (acceptEncodings.Contains("gzip")) return "gzip";
    if (acceptEncodings.Contains("deflate")) return "deflate";
    return "unencoded";
}

最后,您应该告诉客户端他们需要在同一个标​​头上更改缓存。在Accept-Encoding的情况下,用户代理不太可能改变这一点,但这是正确的事情。唉,some browsers无论如何都会忽略这一点。

app.Response.Cache.VaryByHeaders["Accept-Encoding"] = true;