2009-10-15 17 views
103

Tengo una comunicación HTTP a un servidor web que solicita datos JSON. Me gustaría comprimir esta secuencia de datos con Content-Encoding: gzip. ¿Hay alguna manera de configurar Accept-Encoding: gzip en mi HttpClient? La búsqueda de gzip en las referencias de Android no muestra nada relacionado con HTTP, como puede ver here.Android: la comunicación HTTP debe usar "Aceptar codificación: gzip"

+1

[Android-WebRequest] (https://github.com/delight-im/Android-WebRequest) admite GZIP y respuestas sin comprimir automáticamente, p. Ej. con 'new WebRequest(). get(). to (" http://www.example.com/ ") .askForGzip (true) .executeSync()'. Específicamente, el método [parseResponse (...)] (https://github.com/delight-im/Android-WebRequest/blob/master/src/im/delight/android/webrequest/WebRequest.java) debería ser lo que estas buscando. – caw

Respuesta

168

Debe utilizar cabeceras HTTP para indicar una conexión puede aceptar datos codificados gzip, por ejemplo: respuesta

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

Comprobar para codificación de contenido:

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

Esa es una gran y muy útil respuesta con todos los detalles que necesitaba. Muchas gracias. Un comentario: en lugar de addHeader utilicé setHeader. Por lo que entiendo, esto sobrescribe la "codificación de aceptación" existente si la hay. No estoy seguro de cuál es el enfoque correcto/mejor. Para sobrescribir un encabezado existente para asegurarse de que tiene el valor correcto o para agregarlo en caso de que pueda haber otros encabezados de aceptación de codificación en paralelo. – znq

+0

¿dónde pones el instream entonces? – Mikey

+7

esto no descomprime la solicitud, solo le dice al servidor que puede aceptar una respuesta gzip'd. –

2

No he usado GZip, pero supongo que debe usar el flujo de entrada de HttpURLConnection o HttpResponse como GZIPInputStream, y no de otra clase específica.

+0

HTTPURLConnection tiene gzip activado por defecto. Solo necesita asegurarse de que su servidor web pueda devolver páginas gzip. http://developer.android.com/reference/java/net/HttpURLConnection.html Pude devolver páginas gzip de php utilizando ob_start ("ob_gzhandler"); – metric152

13

creo que el ejemplo de código en este enlace es más interesante: ClientGZipContentCompression.java

Están usando HttpRequestInterceptor y HttpResponseInterceptor

muestra para solicitud:

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

     }); 

muestra para la respuesta:

 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

¿Por qué crees que es más interesante? –

+3

@codingcrow Esto es lo que está buscando: _En este caso particular, el cliente HTTP puede hacer una compresión GZIP de contenido transparente agregando dos interceptores de protocolo: un interceptor de solicitud que agrega el encabezado 'Aceptar-Codificar: gzip' a todas las solicitudes salientes y interceptor de respuesta que expande automáticamente las entidades de respuesta comprimidas al envolverlas con una clase de decorador sin comprimir. El uso de interceptores de protocolo hace que la compresión de contenido sea completamente transparente para el consumidor de la interfaz HttpClient._ – clauziere

+0

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

33

Si está usando API de nivel 8 o superior hay AndroidHttpClient.

Tiene métodos auxiliares como:

public static InputStream getUngzippedContent (HttpEntity entity) 

y

public static void modifyRequestToAcceptGzipResponse (HttpRequest request) 

conduce a código mucho más sucinta:

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

Nice tip the modifyRequest & getUngzipped, también, necesitaba copiar EntityUtils.toString (HttpEntity) para analizar la secuencia no fragmentada como String –

+1

AndroidHttpClient quedó obsoleto en el nivel de API 22. –

+0

Pasé aproximadamente una hora para encontrar la mejor solución. ¡¡¡Esta es la mejor respuesta!!! Gracias – shift66

0

En mi caso fue así:

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