2012-10-23 7 views
29

Chcę wysłać skompresowane dane POST z Javascriptem do kontrolowanego przeze mnie serwera. Czy istnieje sposób, aby warstwa HTTP radziła sobie z kompresją?Kompresja danych postów HTTP wysłanych z przeglądarki

Wysyłam JSON. Jeśli ustawię typ zawartości na GZIP/deflate, przeglądarka automatycznie ją skompresuje, a następnie Apache z modem deflate automatycznie ją rozpakuje, aby moja aplikacja nie musiała w ogóle myśleć o kompresowanych danych?

Wiem, że może działać na odwrót, ale w jakikolwiek sposób, aby to działało w ten sposób?

Odpowiedz

63

Czy przeglądarka automatycznie zakoduje twoje dane za pomocą kodu-gzip? Krótka odpowiedź to ...

HAAHAHAAhahahahahhaha.

Długa odpowiedź jest, że niektóre klienty użytkownika mogą robić takie rzeczy, ale na pewnonie można na nim polegać. Stan dokumentacji apache mod_deflate:

niektóre aplikacje specjalne faktycznie obsługują kompresję żądań, na przykład niektóre klienty WebDAV.

Tak, nie, to nie zadziała. Musisz samodzielnie wygenerować odpowiednią wiadomość żądania HTTP. Odpowiednim nagłówkiem w tym przypadku jest Content-Encoding: gzip i NOT Content-Type:, ponieważ sama treść to application/json, po prostu chcesz zakodować treść encji komunikatu żądania HTTP do transportu.

Należy również dodać odpowiedni nagłówek Content-Length: określający rozmiar w bajtach treści encji wiadomości po kompresji -OR- wysłać wiadomość HTTP za pomocą Transfer-Encoding: chunked i zrezygnować ze specyfikacji długości treści.

Na końcu odbiorczym, ty możeinstruct mod_deflate to use an input filter dekompresji informacje:

<Location /dav-area> 
SetInputFilter DEFLATE 
</Location> 

To jest trochę ciężki przekazał jeśli tylko dostawanie sprężone treść wiadomości na kilka zasobów. Zamiast tego prawdopodobnie powinieneś po prostu użyć skryptu po stronie klienta, aby sprawdzić nagłówek Content-Encoding: gzip i zdekompresować treść żądania ręcznie. Jak to zrobić, powiedzmy, PHP, to zupełnie inne pytanie. Jeśli potrzebujesz szczegółowych informacji, powinieneś zamieścić kolejne pytanie.

+0

Chciałbym dodać, że jeśli wysyłasz małe serie tekstu JSON, obciążenie przetwarzania potrzebne do skompresowania danych prawdopodobnie przeważy mniejsze korzyści związane z wielkością transferu. Jeśli mówisz o przesyłaniu plików binarnych w swoich żądaniach, to jest inna historia. Ale dla JSON? Prawdopodobnie nie warto poświęcić czasu. – rdlowrey

+0

Doszedłem do wniosku, że nie mogę tego zrobić, ale powiedziałem, że o to zapytam. Mam wersję, w której kompresuję jedno z pól JSON i rozpakowuję w aplikacji (Sinatra). Myślę, że to może być najlepszy sposób na zrobienie tego w mojej sytuacji. Informacje w tym polu są przyzwoite, więc kompresja jest przydatna. Dziękuję –

+121

Zauważ, że "HAAHAHAAahahahahahhaha." jest bardzo ściśliwy. –

0

Po prostu to osiągnięto przy użyciu https://github.com/dankogai/js-deflate Jednak dane posta z dowolnego powodu usuwają znaki + i zastępują je spacjami.

Aby wysłać dane za pośrednictwem javascript:

params.mapdata= btoa(RawDeflate.deflate(JSON.stringify(mapdata))); 

Aby odbierać dane poprzez php:

$value = gzinflate(base64_decode(preg_replace('/\s/', '+',$value))); 
+3

Dane POST muszą być zakodowane za pomocą adresu URL, dlatego '+' należy wysłać jako '% 2B'. '+ 'to stare kodowanie dla białej przestrzeni. –

+1

wydaje się to błędne. btoa rozszerza dane o 30% - więc kompresujesz tekst do pliku binarnego, a następnie rozwijasz binarnie z powrotem do tekstu. Prawdopodobnie zwiększy to transport. – cnd

1

Jest to możliwe, ale polecam zdecydowanie przeciwko zaakceptowaniu zgzipowanego przychodzące dane do serwera. Głównym powodem jest uniemożliwienie Twojemu serwerowi uzyskania gzip bombed.Zwykle nie można dowiedzieć się, jak wyglądają nieskompresowane dane, zanim faktycznie je rozpakowujemy, aby użytkownik mógł wysłać żądanie sieci, które wygląda jak nieszkodliwe 1 KB lub 1 MB danych, ale jest to naprawdę 100 GB danych, a następnie sieć. serwer (nginx lub apache) zawiesza się na następne 10 minut, próbując zdekompresować to wszystko, w końcu skończy się pamięć/blokowanie.