使用HttpWebRequest对象发出请求时,我需要调用方法GetResponse()来发送请求并获取响应。
此方法的问题在于,在收到所有数据之前,它不会返回响应对象。假设我正在下载一个100 MB的文件,在响应完成并且下载了所有100 MB之前,我将无法读取它。
我想要的是能够在它们到达时立即读取响应流字节,而无需等待响应完成
我知道我可以使用Range Http标头,但它对我的情况不起作用。
答案 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发布的示例。它再一次证明它工作正常,没有任何特殊的黑客攻击。