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

时间:2010-05-15 22:29:10

标签: c# http httpwebrequest httpwebresponse

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

4 个答案:

答案 0 :(得分:8)

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

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

您可以尝试使用一些“较短”的网址进行测试。这里的示例开始下载debian发行版的ISO(略大于600 MByte)。 对不起debian,我的意思并不是要窃取你的带宽。 - >顺便说一句:是否有一些可以用来测试这种情况的合理的东西?

“守则”受到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));
        }
    }
}

答案 1 :(得分:3)

我一直在寻找相同的东西:服务器流分块的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并查看是否应用程序现在连续正常流程(即读取流)。

答案 2 :(得分:1)

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

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

}

答案 3 :(得分:0)

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

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

如果你没有得到相同的行为(这真的很奇怪,而且不应该发生),你可以添加一个代码示例,但是我没有像上面解释的那样工作吗?

另外,请测试scherand发布的示例。它再一次证明它工作正常,没有任何特殊的黑客攻击。