2009-10-15 6 views
103

Ho una comunicazione HTTP a un server web che richiede dati JSON. Mi piacerebbe comprimere questo flusso di dati con Content-Encoding: gzip. C'è un modo per impostare Accept-Encoding: gzip nel mio HttpClient? La ricerca di gzip nei Riferimenti Android non mostra nulla correlato a HTTP, come si può vedere here.Android: la comunicazione HTTP deve utilizzare "Accept-Encoding: gzip"

+1

[Android-WebRequest] (https://github.com/delight-im/Android-WebRequest) supporta automaticamente GZIP e le risposte non compresse, ad es. con 'new WebRequest(). get(). a (" http://www.example.com/ ") .askForGzip (true) .executeSync()'. Nello specifico, il metodo [parseResponse (...)] (https://github.com/delight-im/Android-WebRequest/blob/master/src/im/delight/android/webrequest/WebRequest.java) dovrebbe essere quello che stai cercando. – caw

risposta

168

Si dovrebbe usare intestazioni HTTP per indicare una connessione può accettare dati codificati gzip, ad esempio:

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

controllare la risposta per la codifica di contenuti:

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

Questa è una risposta fantastica e molto utile con tutti i dettagli di cui avevo bisogno. Molte grazie. Un commento: invece di addHeader ho usato setHeader. Da quanto ho capito, questo sovrascrive l'esistente "Accept-Encoding" se ce n'è uno. Non sono sicuro quale sia l'approccio giusto/migliore. Per sovrascrivere un'intestazione esistente per assicurarsi che abbia il valore corretto o per aggiungerla nel caso in cui possano esserci altre intestazioni Accept-Encoding in parallelo. – znq

+0

dove metti l'instream allora? – Mikey

+7

questo non gzip la richiesta, dice solo al server che è possibile accettare una risposta gzip. –

2

Non ho usato GZip, ma suppongo che dovresti usare lo stream di input dal tuo HttpURLConnection o HttpResponse come GZIPInputStream, e non qualche altra specifica classe.

+0

HTTPURLConnection ha gzip attivato per impostazione predefinita. Devi solo assicurarti che il tuo server web possa restituire pagine gzip. http://developer.android.com/reference/java/net/HttpURLConnection.html Sono riuscito a restituire pagine gzip da php utilizzando ob_start ("ob_gzhandler"); – metric152

13

penso che l'esempio di codice a questo link è più interessante: ClientGZipContentCompression.java

Si utilizza HttpRequestInterceptor e HttpResponseInterceptor

Esempio per la richiesta:

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

     }); 

di esempio per la risposta:

 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

Qualche motivo per cui pensi che sia più interessante? –

+3

@codingcrow Ecco cosa stai cercando: _ In questo caso particolare, il client HTTP è in grado di comprimere il contenuto GZIP in modo trasparente aggiungendo due intercettori di protocollo: un intercettore di richiesta che aggiunge l'intestazione "Accept-Encoding: gzip" a tutte le richieste in uscita e un interceptor di risposta che espande automaticamente le entità di risposta compresse avvolgendole con una classe decoratore non comprendente. L'uso di intercettatori di protocollo rende la compressione del contenuto completamente trasparente per il consumatore dell'interfaccia HttpClient._ – clauziere

+0

[Source] (http://hc.apache.org/httpcomponents-client-ga/httpclient/examples/org/apache/http/ esempi/client/ClientGZipContentCompression.java) – clauziere

33

Se stai usando livello di API 8 o superiore c'è AndroidHttpClient.

Ha metodi di supporto come:

public static InputStream getUngzippedContent (HttpEntity entity) 

e

public static void modifyRequestToAcceptGzipResponse (HttpRequest request) 

che porta a codice molto più succinta:

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

Consiglio di modificare il comando ModificaRequest e getUngzipped, inoltre, avevo bisogno di copiare EntityUtils.toString (HttpEntity) per analizzare lo stream ungzipeed come String –

+1

AndroidHttpClient è stato ritirato al livello API 22 –

+0

Abbiamo trascorso circa un'ora per trovare la soluzione migliore. Questa è la migliore risposta !!! Grazie – shift66

0

Nel mio caso è stato così:

URLConnection conn = ...; 
InputStream instream = conn.getInputStream(); 
String encodingHeader = conn.getHeaderField("Content-Encoding"); 
if (encodingHeader != null && encodingHeader.toLowerCase().contains("gzip")) 
{ 
    instream = new GZIPInputStream(instream); 
}