При создании использования запроса объектом HttpWebRequest я должен назвать метод GetResponse (), чтобы отправить запрос и вернуть ответ.
Проблема с этим методом состоит в том, что он не возвращает объект ответа, пока все данные не были получены. Скажите, что я загружаю файл на 100 МБ, я не смогу считать его, пока конец ответа и все 100 МБ не будет загружен.
То, что я хочу, должно смочь считать байты ответного потока, как только они прибывают, не ожидая ответа для завершения.
Я знаю, что могу использовать Диапазон заголовок Http, но он не будет работать над моей ситуацией.
Я думаю, это очень близко к тому, что предлагает @Zachary. И это (кажется) работает (работает); на самом деле я думаю, что использование using
, как делает @Zachary, даже "приятнее".
GetResponse()
, которое вы (похоже) описали.
Кроме того, следующий код только приблизительно показывает, как все работает; он не будет читать поток до конца, например (если только по совпадению :)). Но он должен работать, если вы скопируете и вставите его в пустой проект "Console Application" в Visual Studio.
Вы можете попробовать использовать какой-нибудь "более короткий" URL для теста. В примере здесь начинается загрузка ISO дистрибутива debian (чуть больше 600 МБайт). Извините, debian, я не хотел красть вашу пропускную способность. -> Btw: есть ли что-то разумное, что можно использовать для тестирования такого сценария?
Код сильно вдохновлен C# - Как читать непрерывный поток XML по 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));
}
}
}
Если вы установите размер буфера при чтении, вы можете читать данные по частям ... пример ...
// 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 ()
, который представляет собой фактический поток данных, загружаемый с сервера.И вы можете легко получить доступ к потоку ответов ДО того, как будет загружен весь файл. Это 100% правда и проверено.
Если вы не получаете такое же поведение (что действительно странно и не должно происходить), можете ли вы добавить пример кода, который не работает, как я объяснил выше?
Также проверьте пример, опубликованный Scherand . Это лишний раз доказывает, что все работает нормально, без особых хитростей.