如何在Http响应完成之前读取响应流

使用HttpWebRequest对象发出请求时,我需要调用方法GetResponse()来发送请求并获取响应。
此方法的问题在于,在收到所有数据之前,它不会返回响应对象。 假设我正在下载一个100 MB的文件,在响应完成并且下载了所有100 MB之前,我将无法读取它。
我想要的是能够在它们到达时立即读取响应流字节,而无需等待响应完成。
我知道我可以使用Range Http标头,但它不适用于我的情况。

我认为这与@Zachary建议的非常接近。 它(似乎)工作; 实际上我认为使用@Zachary using甚至“更好”。
我的主要观点是我看不到你(似乎)描述的GetResponse()的阻塞行为。

此外,以下代码仅粗略地显示了一切如何工作; 例如,它不会将流读到最后 (除非巧合:))。 但是,如果将它复制粘贴到Visual Studio中的空“控制台应用程序”项目中,它应该可以工作。

您可以尝试使用一些“较短”的URL进行测试。 这里的例子开始下载debian发行版的ISO(略大于600 MByte)。 对不起debian,我不是故意偷你的带宽。 – >顺便说一下:有什么明智的东西可以用来测试这样的场景吗?

该代码受C#的强烈启发- 如何通过HTTP读取连续的XML流 。

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

我一直在寻找同样的事情:服务器流分块的XML数据,我需要一个C#客户端,可以在服务器流式传输时访问这些数据。 我尝试了许多不同的方法来访问源(WebChannelFactory,WebClient,HttpWebRequest / Response,TcpClient)但到目前为止失败了。 找到这个线程我专注于HttpWebRequest / Response,其中我遇到了跟​​随以下行阻塞的相同问题:

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

正如Artiom Chilaru所说,如果它阻塞了:有些东西是错的,因为它不应该。 现在专注于尝试通过下载大型.ISO文件来复制默认行为,我发现Fiddler阻止了GetResponse()方法!

但是,一旦设置了流(即已经调用了GetResponse()),打开Fiddler就没有问题了,但是在HTTP GET期间如果发现GetResponse()阻塞,请尝试关闭Fiddler并查看您的应用程序现在是否连续这是正常的流程(即读取流)。

如果在读取时设置缓冲区大小,则可以读取块中的数据…示例…

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

我不确定你有什么,但我知道一个事实(我相信很多人会同意这里), GetResponse()不会下载整个文件。 它将发送请求,等待响应,并获取响应头。

获得响应后,可以使用GetResponseStream()轻松获取响应流, GetResponseStream()是从服务器下载的实际数据流。 您可以在下载整个文件之前轻松访问响应流。 这是100%真实和测试。

如果你没有得到相同的行为(这真的很奇怪,而且不应该发生)你能添加一个代码示例吗?

另外,测试一下scherand发布的示例 。 它再次certificate它工作得很好,没有任何特殊的黑客攻击。