2012-08-22 12 views
11

Me estoy dirigiendo a un servicio web REST desde Android 4.0 utilizando HttpsURLConnection. Esto funciona bien a menos que intente POST algo. Esta es la sección de código correspondiente:¿Cómo desactivo explícitamente el modo de transmisión por secuencias para las conexiones HTTP en Android?

connection.setDoOutput(true); 
    connection.setChunkedStreamingMode(0); 

    ByteArrayOutputStream out = new ByteArrayOutputStream(); 
    serializeObjectToStream(out, object); 
    byte[] array = out.toByteArray(); 
    connection.getOutputStream().write(array, 0, array.length); 

Esto desencadena la siguiente excepción:

java.net.HttpRetryException: Cannot retry streamed HTTP body 

De depuración Me di cuenta de que el flujo de salida consigo a través de connection.getOuputStream() es de tipo ChunkedOutputStream y de la excavación en el código fuente de los androides Pensé que si una solicitud necesita ser reintentada (por la razón que sea), se activa con la excepción anterior, porque se da cuenta de que es no usando un RetryableOutputStream que quiere allí.

La pregunta ahora es: ¿Cómo puedo hacer que mi HttpsURLConnection devuelva un RetryableOutputStream, o más bien, cómo puedo prevenir la codificación de solicitud fragmentada correctamente? Yo pensé hice que ya con setChunkedStreamingMode(0), pero parece que esto no es el caso ...

[editar]

No, la implementación de un java.net.HTTPUrlConnection ignora el modo de transmisión de 0 o menor:

public void setChunkedStreamingMode(int chunkLength) { 
    [...] 
    if (chunkLength <= 0) { 
     this.chunkLength = HttpEngine.DEFAULT_CHUNK_LENGTH; 
    } else { 
     this.chunkLength = chunkLength; 
    } 
} 
+0

En una nota relacionada: Creo que la razón _por qué_ que quiere una RetryableOutputStream en absoluto es porque hay una protección autenticación básica configurado en el servidor REST y el HttpURLConnectionImpl de Android parecen volver a intentar automáticamente una solicitud cuando recibe una respuesta 401 no autorizada. –

Respuesta

12

Bummer! La solución es no llamar al setChunkedStreamingMode() (¡ni siquiera a setFixedStreamingMode()) desde el código del cliente! "-1" son los valores predeterminados internos para fixedLength y chunkedLength y no pueden establecerse en el lado del cliente, porque establecer un valor inferior o igual a "0" lo deja como predeterminado a HttpEngine.DEFAULT_CHUNK_LENGTH (o arroja una excepción en el caso del modo de transmisión fijo).

2

La solución es establecer un encabezado Content-Length (que se puede configurar en la siguiente parte) y llamar al setFixedLengthStreamingMode con la longitud adecuada del mensaje POST que desea enviar.

Consulte la sección "modo de transmisión" en este SO FAQ:

Using java.net.URLConnection to fire and handle HTTP requests

Cuestiones relacionadas