简体   繁体   English

可以在ASP.NET / IIS 7中有选择地禁用gzip压缩吗?

[英]Can gzip compression be selectively disabled in ASP.NET/IIS 7?

I am using a long-lived asynchronous HTTP connection to send progress updates to a client via AJAX. 我使用长期的异步HTTP连接通过AJAX向客户端发送进度更新。 When compression is enabled, the updates are not received in discrete chunks (for obvious reasons). 启用压缩时,不会以离散块的形式接收更新(出于显而易见的原因)。 Disabling compression (by adding a <urlCompression> element to <system.webServier> ) does solve the problem: 禁用压缩(通过向<system.webServier>添加<urlCompression>元素) 确实解决了问题:

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

However, this disables compression site-wide. 但是,这会在站点范围内禁用压缩。 I would like to preserve compression for every other controller and/or action except for this one. 我想保留每个其他控制器和/或操作的压缩,除了这个。 Is this possible? 这可能吗? Or am I going to have to create a new site/area with its own web.config? 或者我将不得不用自己的web.config创建一个新的站点/区域? Any suggestions welcome. 欢迎任何建议。

PS the code that does the writing to the HTTP response is: PS写入HTTP响应的代码是:

var response = HttpContext.Response;
response.Write(s);
response.Flush();

@Aristos' answer will work for WebForms, but with his help, I've adapted a solution more inline with ASP.NET/MVC methodology. @Aristos的回答将适用于WebForms,但在他的帮助下,我已经采用了更符合ASP.NET / MVC方法的解决方案。

Create a new filter to provide the gzipping functionality: 创建一个新的过滤器以提供gzipping功能:

public class GzipFilter : ActionFilterAttribute
{
    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        base.OnActionExecuted(filterContext);

        var context = filterContext.HttpContext;
        if (filterContext.Exception == null && 
            context.Response.Filter != null &&
            !filterContext.ActionDescriptor.IsDefined(typeof(NoGzipAttribute), true))
        {
            string acceptEncoding = context.Request.Headers["Accept-Encoding"].ToLower();;

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

Create the NoGzip attribute: 创建NoGzip属性:

public class NoGzipAttribute : Attribute {
}

Prevent IIS7 from gzipping using web.config: 使用web.config阻止IIS7进行gzipping攻击:

<system.webServer>
    ...
    <urlCompression doStaticCompression="true" doDynamicCompression="false" />
</system.webServer>

Register your global filter in Global.asax.cs: 在Global.asax.cs中注册全局过滤器:

protected void Application_Start()
{
    ...
    GlobalFilters.Filters.Add(new GzipFilter());
}

Finally, consume the NoGzip attribute: 最后,使用NoGzip属性:

public class MyController : AsyncController
{
    [NoGzip]
    [NoAsyncTimeout]
    public void GetProgress(int id)
    {
        AsyncManager.OutstandingOperations.Increment();
        ...
    }

    public ActionResult GetProgressCompleted() 
    {
        ...
    }
}

PS Once again, many thanks to @Aristos, for his helpful idea and solution. PS再次感谢@Aristos,感谢他的有用的想法和解决方案。

I found a much easier way to do this. 我发现了一种更简单的方法。 Instead of selectively doing your own compression, you can selectively disable the default IIS compression (assuming its enabled in your web.config). 您可以选择性地禁用默认的IIS压缩(假设它在您的web.config中启用),而不是有选择地进行自己的压缩。

Simply remove the accept-encoding encoding header on the request and IIS wont compress the page. 只需删除请求中的accept-encoding编码标头,IIS就不会压缩页面。

(global.asax.cs:) (:)的global.asax.cs

protected void Application_BeginRequest(object sender, EventArgs e)
{
    try
    {
        HttpContext.Current.Request.Headers["Accept-Encoding"] = "";
    }
    catch(Exception){}
}

What about you set the gzip compression by your self, selectivle when you wish for ? 你希望什么时候你自己设置gzip压缩,selectivle? On the Application_BeginRequest check when you like to make and when you dont make compression. 在Application_BeginRequest上检查您何时制作以及何时不进行压缩。 Here is a sample code. 这是一个示例代码。

protected void Application_BeginRequest(Object sender, EventArgs e)
{
    string cTheFile = HttpContext.Current.Request.Path;
    string sExtentionOfThisFile = System.IO.Path.GetExtension(cTheFile);

    if (sExtentionOfThisFile.Equals(".aspx", StringComparison.InvariantCultureIgnoreCase))
    {
        string acceptEncoding = MyCurrentContent.Request.Headers["Accept-Encoding"].ToLower();;

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM