2008-08-19 13 views
12

estoy teniendo problemas para leer un "fragmentada" respuesta cuando se utiliza un StreamReader para leer la secuencia devuelta por GetResponseStream() de un HttpWebResponse:lectura "fragmentada" respuesta con HttpWebResponse

// response is an HttpWebResponse 
StreamReader reader = new StreamReader(response.GetResponseStream()); 
string output = reader.ReadToEnd(); // throws exception... 

Cuando el método es reader.ReadToEnd() llamado Recibo la siguiente System.IO.IOException: No se pueden leer datos de la conexión de transporte: La conexión se cerró.

El código anterior funciona bien cuando el servidor devuelve una respuesta "no fragmentada".

La única forma en que he podido hacer que funcione es utilizar HTTP/1.0 para la solicitud inicial (en lugar de HTTP/1.1, el valor predeterminado), pero esto parece ser una solución intermedia.

¿Alguna idea?


@Chuck

Su solución funciona bastante bien. Todavía arroja la misma IOExeception en la última lectura(). Pero después de inspeccionar los contenidos de StringBuilder parece que se han recibido todos los datos. Así que quizás solo tenga que ajustar Read() en un try-catch y tragar el "error".

+0

para leer la respuesta fragmentada, es necesario seguir http://en.wikipedia.org/wiki/Chunked_transfer_encoding –

+0

que estoy viendo este comportamiento con .NET 4.6 conectando a la API REST HTTP de PowerDNS 3.4.5. Las soluciones no ayudan. Si me trago la excepción, pierdo parte de la respuesta. –

Respuesta

4

No lo he intentado esto con una respuesta "fragmentada" pero ¿algo así funcionaría?

StringBuilder sb = new StringBuilder(); 
Byte[] buf = new byte[8192]; 
Stream resStream = response.GetResponseStream(); 
string tmpString = null; 
int count = 0; 
do 
{ 
    count = resStream.Read(buf, 0, buf.Length); 
    if(count != 0) 
    { 
      tmpString = Encoding.ASCII.GetString(buf, 0, count); 
      sb.Append(tmpString); 
    } 
}while (count > 0); 
+4

Esto es peligroso para codificaciones multibyte (es decir, no ASCII) porque no hay garantía de que las lecturas estén alineadas con los límites de caracteres. – spender

+2

@Chuck No puede usar ASCII, necesita averiguar qué codificación se está utilizando en realidad, es decir, mediante Content-Type y luego usarla para "GetString" –

0

Craig, sin ver la corriente que está leyendo es un poco difícil de depurar, pero tal vez se podría cambiar la configuración de la variable de recuento a esto:

count = resStream.Read(buf, 0, buf.Length-1); 

Es un poco de un truco , pero si la última lectura te está matando y no devuelve ningún dato, teóricamente esto evitará el problema. Todavía me pregunto por qué la transmisión está haciendo eso.

0

He tenido el mismo problema (que es cómo terminé aquí :-). Finalmente lo rastreó hasta el hecho de que la secuencia fragmentada no era válida, faltaba el trozo final de longitud cero. Se me ocurrió el siguiente código que maneja tanto las transmisiones en bloque válidas como las no válidas.

using (StreamReader sr = new StreamReader(response.GetResponseStream(), Encoding.UTF8)) 
{ 
    StringBuilder sb = new StringBuilder(); 

    try 
    { 
     while (!sr.EndOfStream) 
     { 
      sb.Append((char)sr.Read()); 
     } 
    } 
    catch (System.IO.IOException) 
    { } 

    string content = sb.ToString(); 
} 
+2

Lanzar bytes a char es peligroso porque ignora por completo codificaciones multibyte. – spender

1

Estoy trabajando en un problema similar. Las .net HttpWebRequest y HttpWebRequest manejan las cookies y las redirecciones automáticamente, pero no manejan el contenido fragmentado en el cuerpo de la respuesta automáticamente.

Esto se debe quizás a que el contenido fragmentado puede contener más que datos simples (es decir, nombres de fragmentos, encabezados finales).

Simplemente leyendo la secuencia y haciendo caso omiso de la excepción EOF no funcionará ya que la secuencia contiene más que el contenido deseado. La secuencia contendrá fragmentos y cada fragmento comienza declarando su tamaño. Si la secuencia se lee simplemente de principio a fin, los datos finales contendrán los metadatos del fragmento (y en caso de que se muestre contenido, no se verificará el CRC al descomprimir).

Para resolver el problema, es necesario analizar manualmente la secuencia, eliminando el tamaño del fragmento de cada fragmento (así como los delimitadores CR LF), detectando el fragmento final y conservando solo los datos del fragmento. Es probable que haya una biblioteca por ahí que haga esto, no lo he encontrado aún.

recursos Utiles:

http://en.wikipedia.org/wiki/Chunked_transfer_encoding http://tools.ietf.org/html/rfc2616#section-3.6.1

Cuestiones relacionadas