Можно ли выборочно отключить сжатие gzip в ASP.NET/IIS 7? - PullRequest
10 голосов
/ 14 апреля 2011

Я использую долгоживущее асинхронное HTTP-соединение для отправки обновлений прогресса клиенту через AJAX. Когда сжатие включено, обновления не принимаются отдельными порциями (по понятным причинам). Отключение сжатия (добавление элемента <urlCompression> к <system.webServier>) действительно решает проблему:

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

Однако это отключает сжатие по всему сайту. Я хотел бы сохранить сжатие для любого другого контроллера и / или действия, кроме этого. Это возможно? Или мне придется создать новый сайт / область с собственным web.config? Любые предложения приветствуются.

P.S. код, который выполняет запись в ответ HTTP:

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

Ответы [ 3 ]

14 голосов
/ 14 апреля 2011

@ Ответ Аристоса будет работать для WebForms, но с его помощью я адаптировал решение, более соответствующее методологии ASP.NET/MVC.

Создайте новый фильтр, чтобы обеспечить функциональность 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");
            } 
        }
    }
}

Создайте атрибут NoGzip:

public class NoGzipAttribute : Attribute {
}

Запретить сжатие IIS7 с помощью web.config:

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

Зарегистрируйте свой глобальный фильтр в Global.asax.cs:

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

Наконец, используйте атрибут NoGzip:

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

    public ActionResult GetProgressCompleted() 
    {
        ...
    }
}

P.S. Еще раз большое спасибо @Aristos за его полезную идею и решение.

4 голосов
/ 15 сентября 2014

Я нашел гораздо более простой способ сделать это.Вместо выборочного выполнения собственного сжатия можно выборочно отключить сжатие IIS по умолчанию (при условии, что оно включено в вашем файле web.config).

Просто удалите заголовок кодировки accept-encoding в запросе, и IIS не будет сжимать страницу.

(global.asax.cs:)

protected void Application_BeginRequest(object sender, EventArgs e)
{
    try
    {
        HttpContext.Current.Request.Headers["Accept-Encoding"] = "";
    }
    catch(Exception){}
}
3 голосов
/ 14 апреля 2011

Как насчет того, чтобы вы сами установили сжатие gzip, выбирая, когда пожелаете? На Application_BeginRequest проверьте, когда вы хотите сделать, и когда вы не делаете сжатие. Вот пример кода.

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");
        }       
    }
}
...