Pregunta

Tengo problemas para leer una respuesta "fragmentada" cuando uso un StreamReader para leer la secuencia devuelta por GetResponseStream() de un HttpWebResponse:

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

Cuando el reader.ReadToEnd() Se llama al método. Recibo la siguiente excepción 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 pude hacerlo funcionar es usar HTTP/1.0 para la solicitud inicial (en lugar de HTTP/1.1, el valor predeterminado), pero esto parece una solución poco convincente.

¿Algunas ideas?


@Arrojar

Tu solución funciona bastante bien.Todavía arroja la misma IOExeception en la última lectura ().Pero después de inspeccionar el contenido de StringBuilder, parece que se han recibido todos los datos.Entonces, tal vez solo necesite envolver Read() en un try-catch y tragarme el "error".

¿Fue útil?

Solución

No lo he probado con una respuesta "fragmentada", pero ¿funcionaría algo como esto?

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

Otros consejos

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

Quizás esto se deba a que el contenido fragmentado puede contener más que simples datos (es decir:nombres de fragmentos, encabezados finales).

Simplemente leer la transmisión e ignorar la excepción EOF no funcionará ya que la transmisión contiene más contenido del deseado.La secuencia contendrá fragmentos y cada fragmento comienza declarando su tamaño.Si la transmisión simplemente se lee de principio a fin, los datos finales contendrán los metadatos del fragmento (y en caso de que se trate de contenido comprimido con gzip, no pasará la verificación CRC al descomprimirlo).

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 manteniendo solo los datos del fragmento.Probablemente haya una biblioteca en algún lugar que haga esto, pero todavía no la he encontrado.

Recursos útiles:

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

Craig, sin ver la transmisión que estás leyendo es un poco difícil de depurar, pero QUIZÁS puedas cambiar la configuración de la variable de conteo a esto:

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

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

Tuve el mismo problema (que es como terminé aquí :-).Finalmente, lo localicé hasta el hecho de que la secuencia fragmentada no era válida: faltaba el fragmento final de longitud cero.Se me ocurrió el siguiente código que maneja transmisiones fragmentadas válidas e invá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();
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top