Может ли страница отказаться от сжатия IIS 7?

Мои страницы автоматически сжимаются IIS7 с помощью GZIP.

Это здорово... но для одной конкретной страницы мне нужно передать ее пользователю, используя Response.Flush() при необходимости. Но когда сжимается вывод, сервер IIS, кажется, собирает весь мой вывод до тех пор, пока страница не будет выполнена до сжатия и отправки ее клиенту. Это аннулирует мою попытку сбросить содержимое пользователя.

Есть ли способ, чтобы у меня была одна страница отказаться от сжатия?

Один из возможных вариантов

Я решил, что если я вручную настрою тип содержимого на тот, который не соответствует конфигурации IIS в c:\windows\system32\inetsrv\config\applicationhost.config, IIS не будет сжимать его. Например. Response.ContentType = "x-text/html". Это хорошо работает с IE8, поскольку он возвращается для отображения HTML. Но Firefox спросит пользователя, что делать с неизвестным типом файла.

Это может сработать, если бы существовал другой тип Mime, который я мог бы использовать, чтобы браузеры принимали как HTML, что не соответствует в applicationhost.config. Для справки, это типы mime, которые будут сжаты:

   <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" />

Другие варианты?

Существуют ли другие опции для отказа от сжатия?

Ответы

Ответ 1

Невозможно отключить сжатие для определенной страницы, но вы можете для каталога.

Здесь описывается, как отключить статическое сжатие, но оно может работать для динамического сжатия: (Из http://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/502ef631-3695-4616-b268-cbe7cf1351ce.mspx?mfr=true)

Чтобы отключить статическое сжатие только для одного каталога, сначала включите глобальное статическое сжатие (если оно отключено), а затем отключите статическое сжатие в этом каталоге. Например, чтобы включить статическое сжатие для каталога в http://www.contoso.com/Home/StyleSheets, выполните следующие шаги:

  • Включить глобальное статическое сжатие, выполнив следующую команду в командной строке:

adsutil set w3svc/filters/compression/parameters/HcDoStaticCompression true

  1. Отключите статическое сжатие в этом каталоге, выполнив следующую команду в командной строке:

adsutil set w3svc/1/root/Home/StyleSheets/DoStaticCompression false

Ответ 3

Вы можете использовать специально созданный модуль сжатия, например этот:

HTTP-сжатие WebResource.axd и страниц в ASP.NET

С помощью этого должно быть легко настроить, какие файлы включать/исключать.

Ответ 4

Я не знаю, каким способом страницы можно отключить программно во время запроса. Однако вы можете обойти сжатие и отправить лишний мусор, достаточно для gzip для обработки нового блока. Ваши данные заполнения должны быть как можно более случайными, чтобы он не слишком сжался, быстрее заполняя буфер дефляции.

Фактический объем отправляемых данных зависит от конфигураций модуля сжатия.

Ответ 5

если вы выполняете Response.BufferOutput = false, это остановит работу встроенного сжатия, хотя и не чисто. Вы можете получать предупреждения о событиях, которые не могут добавлять заголовки после того, как они уже отправлены клиенту.

Ответ 6

Если вам нужно решение, зависящее только от С#, вы можете адаптировать этот метод, который я написал, чтобы справиться с проблемой в Android-браузере:

/// <summary>
/// Alters the current HTTP request only for Android user agents, in order to disable web page compression so the Android browser will not cut off most of the page content, based on the Content-length HTTP header. 
/// </summary>
public static void fixAndroidPageDisplay()
{
    HttpContext c = HttpContext.Current;
    if (c == null) return;
    HttpRequest r = c.Request;
    if (r == null || r.UserAgent == null) return;
    if (r.UserAgent.ToLowerInvariant().Contains("android"))
    {
        HttpResponse rsp = c.Response;

        if (rsp != null)
        {
            string ce = null;
            foreach (string s in rsp.Headers.Keys)
            {
                if (s != null)
                {
                    if (s.ToLowerInvariant().Equals("content-encoding")) {
                        ce = s;
                    }
                }
            }
            if (ce != null) {
                rsp.Headers[ce] = "text/html";
                rsp.Filter = rsp.OutputStream;
            }
        }
    }
}