Jak zaimplementować kompresję GZip w ASP.NET?

81

Próbuję zaimplementować kompresję GZip dla mojej strony asp.net (w tym moje pliki CSS i JS). Wypróbowałem następujący kod, ale kompresuje on tylko moją stronę .aspx (znalazłem ją z YSlow )

HttpContext context = HttpContext.Current;
context.Response.Filter = new GZipStream(context.Response.Filter, CompressionMode.Compress);
HttpContext.Current.Response.AppendHeader("Content-encoding", "gzip");
HttpContext.Current.Response.Cache.VaryByHeaders["Accept-encoding"] = true;

Powyższy kod kompresuje tylko mój kod strony .aspx (znaczniki), a nie pliki CSS i JS, które są dołączone jako pliki zewnętrzne. Proszę powiedz mi, jak zaimplementować kompresję GZip w ASP.NET przy użyciu kodu (ponieważ jestem na współdzielonym serwerze hostingowym, na którym nie mam dostępu do konfiguracji serwera IIS). A także w powyższym kodzie nie otrzymuję ostatnich dwóch wierszy, dlaczego są używane i jaki jest cel tych wierszy. Proszę wytłumacz!

Prashant
źródło
Niezupełnie duplikat: stackoverflow.com/questions/6992524
jpaugh

Odpowiedzi:

28

Aby skompresować pliki JS i CSS, musisz sobie z tym poradzić na poziomie IIS, ponieważ te pliki są renderowane bezpośrednio, bez środowiska wykonawczego ASP.NET.

Możesz wykonać mapowanie rozszerzenia JSX i CSSX w usługach IIS na plik aspnet_isapi.dll, a następnie skorzystać z kodu pocztowego, ale usługi IIS prawdopodobnie wykonają lepszą pracę za Ciebie.

Nagłówek kodowania treści informuje przeglądarkę, że przed renderowaniem musi rozpakować zawartość. Niektóre przeglądarki i tak są wystarczająco inteligentne, aby to rozgryźć, na podstawie kształtu treści, ale lepiej to po prostu powiedzieć.

Dostępne jest ustawienie Accept-encoding cache, dzięki któremu zbuforowana wersja zawartości spakowanej gzipem nie zostanie wysłana do przeglądarki, która zażądała tylko tekstu / html.

Ben Scheirman
źródło
4
Cześć @Ben, Czy możesz mi powiedzieć, jak skompresować moje pliki za pomocą IIS, jakie wszystkie ustawienia muszę wykonać, Chociaż nie mam dostępu do konfiguracji IIS, ale spróbuję to zrobić. Powiedz mi, jak kompresować pliki za pomocą usług IIS? Dzięki!
Prashant
4
stackoverflow.com/a/6992948/8479 szczegółowo opisuje prostą zmianę w web.config, która jest wymagana w przypadku usług IIS7 lub nowszych.
Rory,
47

Oto rozwiązanie dla plików css i javascript. Dodaj następujący kod do <system.webServer> wewnątrz pliku web.config:

<configuration>
  ...
  <system.webserver>
     ...
      <httpCompression>
        <scheme name="gzip" dll="%Windir%\system32\inetsrv\gzip.dll"/>
        <dynamicTypes>
          <add mimeType="text/*" enabled="true"/>
          <add mimeType="message/*" enabled="true"/>
          <add mimeType="application/javascript" enabled="true"/>
          <add mimeType="*/*" enabled="false"/>
        </dynamicTypes>
        <staticTypes>
          <add mimeType="text/*" enabled="true"/>
          <add mimeType="message/*" enabled="true"/>
          <add mimeType="application/javascript" enabled="true"/>
          <add mimeType="*/*" enabled="false"/>
        </staticTypes>
      </httpCompression>
      <urlCompression doStaticCompression="true" doDynamicCompression="true"/>
    ...
  </system.webserver>
  ...
<configuration>

Kredyt: Jak GZipować w ASP.NET i GoDaddy

dortzur
źródło
4
ostatnia linia powinna zostać usunięta
JeffT
1
prawda, ale tak naprawdę dodałbym otwierający <system.webServer> ... więc wiemy, gdzie umieścić konfigurację.
Carlos R Balebona
Dodałem ten sam kod, ale pliki nie są kompresowane
Zeeshan Ahmad Khalil
Czy muszę dodać coś jeszcze?
Zeeshan Ahmad Khalil
16

może się to przydać, gdy go wypróbujesz, akceptuje to kompresję deflate i gzip.

    void Application_PreRequestHandlerExecute(object sender, EventArgs e)
    {
        HttpApplication app = sender as HttpApplication;
        string acceptEncoding = app.Request.Headers["Accept-Encoding"];
        Stream prevUncompressedStream = app.Response.Filter;

        if (app.Context.CurrentHandler == null)
            return;

        if (!(app.Context.CurrentHandler is System.Web.UI.Page ||
            app.Context.CurrentHandler.GetType().Name == "SyncSessionlessHandler") ||
            app.Request["HTTP_X_MICROSOFTAJAX"] != null)
            return;

        if (acceptEncoding == null || acceptEncoding.Length == 0)
            return;

        acceptEncoding = acceptEncoding.ToLower();

        if (acceptEncoding.Contains("deflate") || acceptEncoding == "*")
        {
            // deflate
            app.Response.Filter = new DeflateStream(prevUncompressedStream,
                CompressionMode.Compress);
            app.Response.AppendHeader("Content-Encoding", "deflate");
        }
        else if (acceptEncoding.Contains("gzip"))
        {
            // gzip
            app.Response.Filter = new GZipStream(prevUncompressedStream,
                CompressionMode.Compress);
            app.Response.AppendHeader("Content-Encoding", "gzip");
        }
    } 
Nudier Mena
źródło
2
Wielkie dzięki za ten kod. Musiałem zgzipować / opróżnić zawartość określonej witryny.Nie mam dostępu do konsoli IIS i to mi pomogło. Tylko pytanie: ten kod wydaje się usuwać wszystkie pliki aspx i gziping CSS i ScriptResources, ale nie jest to gzipowanie żadnych plików .js. Czy jest na to sposób? Dzięki.
Rafael Merlin
To jest złe, ponieważ nie są obsługi jakości nauczania takiego: gzip;q=0,deflate. singular.co.nz/2008/07/…
oligofren
11

Powodem, dla którego kompresuje tylko plik ASPX, jest to, że napisany kod jest osadzony tylko w pliku ASPX. Plik ASPX to żądanie oddzielne od wszelkiej zawartej w nim połączonej zawartości. Więc jeśli masz stronę ASPX, która zawiera:

<img src="www.example.com\exampleimg.jpg" alt="example" />

Oznaczałoby to 2 żądania (pomijając wyszukiwania DNS) z przeglądarki do zasobów:

  1. dla strony aspx i
  2. dla obrazu zawartego na stronie aspx.

Każde żądanie ma własną odpowiedź. Opublikowany kod jest dołączany tylko do strumienia odpowiedzi ASPX, dlatego kompresowana jest tylko strona ASPX. Wiersze 1 i 2 twojego opublikowanego kodu zasadniczo przejmują normalny strumień odpowiedzi strony i wprowadzają jakiś kod „pośredniego człowieka”, który w tym przypadku zjada i kompresuje normalny strumień wyjściowy za pomocą strumienia GZip i zamiast tego przesyła go dalej.

Wiersze 3 i 4 konfigurują nagłówki odpowiedzi. Wszystkie żądania i odpowiedzi HTTP mają nagłówki, które są wysyłane przed treścią. Konfigurują one żądanie / odpowiedź, aby serwer i klient wiedzieli, co jest wysyłane i jak.

W tym przypadku wiersz 3 informuje przeglądarkę klienta, że ​​strumień odpowiedzi jest kompresowany za pomocą programu gzip i dlatego przed wyświetleniem musi zostać zdekompresowany przez przeglądarkę klienta.

Linia 4 po prostu włącza nagłówek Accept-Encoding odpowiedzi. W przeciwnym razie nie byłoby tego odpowiedzi.

Istnieją dołączane moduły, które można zapisywać / uzyskiwać, które pozwalają na kompresję wielu innych typów MIME, takich jak * .js i * .css, ale lepiej jest po prostu używać wbudowanej funkcji kompresji usług IIS.

Nie powiedziałeś, której wersji IIS używasz, ale gdyby był to IIS 7.0, wymagałoby to umieszczenia czegoś podobnego do poniższego w <system.webserver>sekcji twojego pliku web.config:

<httpCompression> 
  <scheme name="gzip" dll="%Windir%\system32\inetsrv\gzip.dll" /> 
 <staticTypes>
         <add mimeType="text/*" enabled="true" />
      </staticTypes>
</httpCompression> 
<urlCompression doStaticCompression="true" /> 

..

Richard

współzależność
źródło
Naprawdę
niesamowite
3

W IIS7 wszystkie żądania trafiają do .net, więc należałoby utworzyć HttpModule, który dodawałby te nagłówki do wszystkich odpowiedzi.

Bez usług IIS7 i na hostingu współdzielonym należałoby utworzyć procedurę obsługi mapującą rozszerzenie pliku .net, którego nie używasz (na przykład .asmx), aw pliku web.config określić, że pliki .asmx mają trafiać do HttpHandler, który jest ustawiony przepisać ścieżkę do .jpg lub cokolwiek innego i ustawić tam również nagłówek.

missaghi
źródło
2

Aby odpowiedzieć na Twoje ostatnie pytanie. Te dwie linie ustawiają nagłówki HTTP dla odpowiedzi wysyłanej z powrotem do przeglądarki. Content-Encodinginformuje przeglądarkę, że odpowiedź jest zakodowana jako gzip i musi zostać zdekodowana. Ostatnia linia dodaje Accept-Encodingdo nagłówka Vary . Dzięki temu przeglądarka lub serwery proxy mogą określić, czy odpowiedź była unikatowa lub czy mają na nią wpływ niektóre inne nagłówki i dostosować ich buforowanie.

gix
źródło
0

Dodaj rozszerzenie .aspx do pliku .css lub .js. Użyj <% @ Page ContentType = "text / css"%> lub JavaScript w pliku, aby wyświetlać go z poprawnym typem MIME. i użyj przepisywania adresu URL, aby ukryć to przed przeglądarkami klienta użytkownika. Nagłówek odpowiedzi kodowania treści jest dołączany do gzip, aby wskazać, że gzip jest metodą używaną do wykonywania kompresji. Zróżnicowane ustawienie nagłówka odpowiedzi na Accept-Encoding, aby wszystkie pamięci podręczne wiedziały, która strona (skompresowana lub nieskompresowana) powinna być obsługiwana, zależy od nagłówka Accept-Encoding żądania. Opisałem to na https://stackoverflow.com/a/14509007/1624169

Chawathe Vipul S.
źródło
0

Możesz po prostu dodać następujące elementy do swojego pliku web.config w <system.webServer>elemencie:

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

UWAGA: Jeśli używasz starszej wersji usług IIS (mniej niż 7.5), możesz ustawić parametr doDynamicCompression na wartość false, ponieważ proces intensywnie wykorzystywał procesor. Te problemy zostały rozwiązane w usługach IIS 7.5.

Źródła: https://docs.microsoft.com/en-us/iis/configuration/system.webserver/urlcompression

Stóg
źródło
0

Zrób to za pomocą pliku web.config

<system.webServer>
    <httpCompression>
        <scheme name="gzip" dll="%Windir%\system32\inetsrv\gzip.dll"/>
        <dynamicTypes>
            <add mimeType="text/*" enabled="true"/>
            <add mimeType="message/*" enabled="true"/>
            <add mimeType="application/javascript" enabled="true"/>
            <add mimeType="*/*" enabled="false"/>
        </dynamicTypes>
        <staticTypes>
            <add mimeType="text/*" enabled="true"/>
            <add mimeType="message/*" enabled="true"/>
            <add mimeType="application/javascript" enabled="true"/>
            <add mimeType="*/*" enabled="false"/>
        </staticTypes>
    </httpCompression>
    <urlCompression doStaticCompression="true" doDynamicCompression="true"/>
</system.webServer>

Lub możesz to zrobić za pośrednictwem usług IIS. Aby skompresować pliki JS i CSS, musisz sobie z tym poradzić na poziomie IIS, ponieważ te pliki są renderowane bezpośrednio, bez środowiska wykonawczego ASP.NET.

Możesz wykonać mapowanie rozszerzenia JSX i CSSX w usługach IIS na plik aspnet_isapi.dll, a następnie skorzystać z kodu pocztowego, ale usługi IIS prawdopodobnie wykonają lepszą pracę za Ciebie.

Nagłówek kodowania treści informuje przeglądarkę, że przed renderowaniem musi rozpakować zawartość. Niektóre przeglądarki i tak są wystarczająco inteligentne, aby to rozgryźć, na podstawie kształtu treści, ale lepiej to po prostu powiedzieć.

Dostępne jest ustawienie Accept-encoding cache, dzięki któremu zbuforowana wersja zawartości spakowanej gzipem nie zostanie wysłana do przeglądarki, która zażądała tylko tekstu / html.

Kod
źródło