Android: HTTP iletişimi "Accept-Encoding: gzip" kullanmalıdır


109

JSON verilerini isteyen bir web sunucusuyla bir HTTP iletişimim var. Bu veri akışını ile sıkıştırmak istiyorum Content-Encoding: gzip. Accept-Encoding: gzipHttpClient'imde ayarlayabileceğim bir yol var mı ? gzipAndroid Referanslarındaki arama , burada görebileceğiniz gibi HTTP ile ilgili hiçbir şeyi göstermez .


1
Android-WebRequest , GZIP ve sıkıştırılmamış yanıtları otomatik olarak destekler, örn new WebRequest().get().to("http://www.example.com/").askForGzip(true).executeSync(). Özellikle, aradığınız yöntem parseResponse (...) olmalıdır.
2014

Yanıtlar:


174

Bir bağlantının gzip kodlu verileri kabul edebileceğini belirtmek için http başlıklarını kullanmalısınız, örneğin:

HttpUriRequest request = new HttpGet(url);
request.addHeader("Accept-Encoding", "gzip");
// ...
httpClient.execute(request);

İçerik kodlaması için yanıtı kontrol edin:

InputStream instream = response.getEntity().getContent();
Header contentEncoding = response.getFirstHeader("Content-Encoding");
if (contentEncoding != null && contentEncoding.getValue().equalsIgnoreCase("gzip")) {
    instream = new GZIPInputStream(instream);
}

7
Bu, ihtiyacım olan tüm ayrıntılarla birlikte harika ve çok faydalı bir cevap. Çok teşekkürler. Bir yorum: addHeader yerine setHeader kullandım. Anladığım kadarıyla bu, varsa mevcut "Kabul Et-Kodlamayı" geçersiz kılar. Hangi yaklaşımın doğru / daha iyi olduğundan emin değilim. Doğru değere sahip olduğundan emin olmak için mevcut bir üstbilginin üzerine yazmak veya paralel olarak başka Accept-Encoding üstbilgileri olması durumunda eklemek.
znq

o zaman yayın içi videoyu nereye koyuyorsunuz?
Mikey

7
bu, isteği gzip etmez, yalnızca sunucuya gzip'lenmiş bir yanıtı kabul edebileceğinizi söyler.
Jeffrey Blattman

1
Bunu Google hizmetleri için hazırlayıp çalıştırmakta sorun yaşayan herkes için, burada öğrenmem oldukça zaman alan iki sorun var: (1) bazı Google hizmetleri gzip, gerçekten etkinleştirmek için istemci tarafından sağlanan kullanıcı aracısı dizesinin dizeyi içermesini gerektirir gzip sıkıştırması. (2) ... Bu çok küçükse Sunucu yanıtı gzip olmayabilir unutmayın
sven

Benim sorunum, gzip başlığının hiçbir yerde görünmemesi. Ağı sunucu tarafında koklamak için Wireshark kullanıyorum ve android'e eklediğim "gzip" başlığından hiçbir iz göremiyorum ...
Ted

33

API seviyesi 8 veya üstünü kullanıyorsanız, AndroidHttpClient var .

Aşağıdaki gibi yardımcı yöntemleri vardır:

public static InputStream getUngzippedContent (HttpEntity entity)

ve

public static void modifyRequestToAcceptGzipResponse (HttpRequest request)

çok daha kısa ve öz kodlara yol açar:

AndroidHttpClient.modifyRequestToAcceptGzipResponse( request );
HttpResponse response = client.execute( request );
InputStream inputStream = AndroidHttpClient.getUngzippedContent( response.getEntity() );

ChangeRequest & getUngzipped için güzel bir ipucu, ayrıca, sıkıştırılmamış akışı String olarak ayrıştırmak için EntityUtils.toString'i (HttpEntity) kopyalamam gerekiyordu
Marcos Vasconcelos

1
AndroidHttpClient, API seviyesi 22'de kullanımdan kaldırıldı.
Alex Kucherenko

13

Bu bağlantıdaki kod örneğinin daha ilginç olduğunu düşünüyorum: ClientGZipContentCompression.java

HttpRequestInterceptor kullanıyorlar ve HttpResponseInterceptor

Talep için örnek:

        httpclient.addRequestInterceptor(new HttpRequestInterceptor() {

            public void process(
                    final HttpRequest request,
                    final HttpContext context) throws HttpException, IOException {
                if (!request.containsHeader("Accept-Encoding")) {
                    request.addHeader("Accept-Encoding", "gzip");
                }
            }

        });

Cevap örneği:

        httpclient.addResponseInterceptor(new HttpResponseInterceptor() {

            public void process(
                    final HttpResponse response,
                    final HttpContext context) throws HttpException, IOException {
                HttpEntity entity = response.getEntity();
                Header ceheader = entity.getContentEncoding();
                if (ceheader != null) {
                    HeaderElement[] codecs = ceheader.getElements();
                    for (int i = 0; i < codecs.length; i++) {
                        if (codecs[i].getName().equalsIgnoreCase("gzip")) {
                            response.setEntity(
                                    new GzipDecompressingEntity(response.getEntity()));
                            return;
                        }
                    }
                }
            }

        });

1
Bunun daha ilginç olduğunu düşünmenizin bir nedeni var mı?
Gaurav Agarwal

3
@codingcrow İşte aradığınız şey: Bu özel durumda, HTTP istemcisi, iki protokol önleyicisi ekleyerek şeffaf içerik GZIP sıkıştırması yeteneğine sahiptir: tüm giden isteklere 'Accept-Encoding: gzip' başlığını ekleyen bir istek durdurucu ve bir yanıt Sıkıştırılmamış bir dekoratör sınıfıyla sarmalayarak sıkıştırılmış yanıt varlıklarını otomatik olarak genişleten engelleyici. Protokol yakalayıcılarının kullanılması, içerik sıkıştırmasını HttpClient arabiriminin tüketicisi için tamamen şeffaf hale getirir.
clauziere


GzipDecompressingEntity, android.jar (2.2) içinde
bulunamıyor

1

Ben GZIP kullanmadıysanız, ancak ben size gelen giriş akışı kullanması gerektiğini varsayılabilir HttpURLConnectionveya HttpResponseolarak GZIPInputStreamdeğil, bazı özel diğer sınıfa.


HTTPURLConnection'da gzip varsayılan olarak açıktır. Web sunucunuzun gzip sayfalarını döndürebildiğinden emin olmanız yeterlidir. developer.android.com/reference/java/net/HttpURLConnection.html gzip sayfalarını ob_start ("ob_gzhandler") kullanarak php'den döndürebildim;
metric152

Bir cevabın olmadığında cevap verme!
Martin.Martinsson

0

Benim durumumda şöyle oldu:

URLConnection conn = ...;
InputStream instream = conn.getInputStream();
String encodingHeader = conn.getHeaderField("Content-Encoding");
if (encodingHeader != null && encodingHeader.toLowerCase().contains("gzip"))
{
    instream = new GZIPInputStream(instream);
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.