2010-05-15 9 views
6

Al realizar una solicitud utilizando el objeto HttpWebRequest, necesito llamar al método GetResponse() para enviar la solicitud y obtener la respuesta.
El problema con este método es que no devuelve el objeto de respuesta hasta que se hayan recibido todos los datos. Digamos que estoy descargando un archivo de 100 MB, no podré leerlo hasta que termine la respuesta y se descarguen todos los 100 MB.
Lo que quiero es poder leer los bytes de la secuencia de respuesta tan pronto como lleguen, sin esperar a que se complete la respuesta.
Sé que puedo usar el encabezado Range Http, pero no funcionará en mi situación.Cómo leer el flujo de respuesta antes de que se complete la respuesta Http

+2

GetResponse() o la devolución de llamada que proporciona para BeginGetResponse() se invoca tan pronto como se leen todos los encabezados de respuesta, pero la respuesta completa no se leerá a menos que sea realmente pequeña o la lea. – Gonzalo

+0

No está claro si el OP ha probado realmente alguna de las soluciones sugeridas y se ha enfrentado a algún problema específico. Según mi experiencia, la transmisión de respuestas solo obtiene la transmisión y, a medida que lees de esa transmisión, la respuesta se descarga, a menos, por supuesto, que se trate de un pequeño fragmento. –

Respuesta

7

creo que esto es muy cercano a lo que sugiere @Zachary. Y (parece) trabajo (s); de hecho, creo que usar using como lo hace @Zachary es incluso más "agradable".
Mi punto principal es que no puedo ver el comportamiento de bloqueo de GetResponse() que (parece) describir.

Además, el siguiente código muestra aproximadamente cómo funciona todo; no leerá la secuencia hasta el final por ejemplo (a menos que coincida :)). Pero debería funcionar si lo copia y lo pega en un proyecto vacío de "Aplicación de consola" en Visual Studio.

Puede intentar usar una URL "más corta" para una prueba. El ejemplo aquí comienza descargando un ISO de la distribución Debian (un poco más de 600 MByte). Lo siento Debian, no quise robar tu ancho de banda. -> Por cierto: ¿hay algo sensato que uno pueda usar para probar tal escenario?

El código está fuertemente inspirado en C# - How to read a continuous stream of XML over HTTP.

namespace StreamReadWebRequest 
{ 
    using System; 
    using System.Collections.Generic; 
    using System.Text; 
    using System.Net; 
    using System.IO; 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      HttpWebRequest req; 
      HttpWebResponse res = null; 

      try 
      { 
       req = (HttpWebRequest)WebRequest.Create(
         "http://cdimage.debian.org/debian-cd/5.0.4/i386/iso-cd/debian-504-i386-CD-1.iso"); 
       res = (HttpWebResponse)req.GetResponse(); 
       Stream stream = res.GetResponseStream(); 

       byte[] data = new byte[4096]; 
       int read; 
       while ((read = stream.Read(data, 0, data.Length)) > 0) 
       { 
        Process(data, read); 
       } 
      } 
      finally 
      { 
       if (res != null) 
        res.Close(); 
      } 
      Console.In.Read(); 
     } 

     private static void Process(byte[] data, int read) 
     { 
      Console.Out.Write(ASCIIEncoding.ASCII.GetString(data)); 
     } 
    } 
} 
+0

Lo mismo ... qué scherand dijo :) – War

1

Si establece el tamaño del búfer en su lectura, se puede leer en los datos en trozos ... ejemplo ...

// Get the response stream 
using(Stream resStream = response.GetResponseStream()) 
{ 

     string parseString = null; 
     int count  = 0; 

     do 
     { 
      // Read a chunk of data 
      count = resStream.Read(buf, 0, buf.Length); 

      if (count != 0) 
      { 
       // Convert to ASCII 
       parseString = Encoding.ASCII.GetString(buf, 0, count); 

       // Append string to results 
       sb.Append(tempString); 
      } 
     } 
     while (count > 0); 

} 
+0

Esto es después de que se complete la respuesta, quiero poder leer la secuencia de respuesta antes de eso. –

0

no estoy seguro de lo que tiene a su lado, pero sé que es un hecho (y estoy seguro de que mucha gente estará de acuerdo aquí) que GetResponse() no se descarga todo el archivo de nuevo. Enviará la solicitud, esperará la respuesta y obtendrá los encabezados de respuesta.

Después de recibir la respuesta, puede obtener fácilmente la secuencia de respuesta con GetResponseStream(), que es la secuencia de datos real que se está descargando desde el servidor. Y puede acceder fácilmente a la secuencia de respuesta ANTES de descargar todo el archivo. Esto es 100% verdadero y probado.

Si no obtiene el mismo comportamiento (que es realmente extraño, y no debería suceder), ¿podría agregar un ejemplo de código que no funciona como he explicado anteriormente?

Además, pruebe el ejemplo publicado por scherand. Simplemente demuestra una vez más que funciona bien, sin ningún truco especial.

3

Estaba buscando lo mismo: el servidor transmite datos XML fragmentados y necesitaba un cliente C# que pudiera acceder a estos datos mientras se está transmitiendo el servidor. Intenté muchas formas diferentes de acceder a la fuente (WebChannelFactory, WebClient, HttpWebRequest/Response, TcpClient), pero hasta el momento no he podido. Encontrar este hilo me he centrado en HttpWebRequest/respuesta en el que tengo el mismo problema que está bloqueando la línea siguiente:

HttpWebResponse resp = (HttpWebResponse)request.GetResponse(); 

Como se ha indicado Artiom Chilaru, si está bloqueando: algo está mal, ya que no debe.Ahora, centrándome en intentar reproducir el comportamiento predeterminado con la descarga de archivos .ISO grandes, descubrí que Fiddler estaba bloqueando el método GetResponse().

Sin embargo, no hay ningún problema para abrir Fiddler una vez que se haya configurado la secuencia (es decir, GetResponse() ya se ha llamado), pero durante el HTTP GET si encuentras que GetResponse() está bloqueando intenta cerrar Fiddler y verifica su aplicación ahora continua es flujo normal (es decir, leyendo la secuencia).

+1

Este fue exactamente mi problema. Una vez que cerré Fiddler, GetResponse() se comportó como se esperaba. ¡Gracias! –

Cuestiones relacionadas