Ошибка "Этот поток не поддерживает операции поиска" в C#
Я пытаюсь получить изображение из URL с помощью byte
поток. Но я получаю это сообщение об ошибке:
Этот поток не поддерживает операции поиска.
Это мой код:
byte[] b;
HttpWebRequest myReq = (HttpWebRequest)WebRequest.Create(url);
WebResponse myResp = myReq.GetResponse();
Stream stream = myResp.GetResponseStream();
int i;
using (BinaryReader br = new BinaryReader(stream))
{
i = (int)(stream.Length);
b = br.ReadBytes(i); // (500000);
}
myResp.Close();
return b;
Что я делаю не так, ребята?
7 ответов
Вы, вероятно, хотите что-то подобное. Либо проверка длины не удалась, либо BinaryReader выполняет поиск за кадром.
HttpWebRequest myReq = (HttpWebRequest)WebRequest.Create(url);
WebResponse myResp = myReq.GetResponse();
byte[] b = null;
using( Stream stream = myResp.GetResponseStream() )
using( MemoryStream ms = new MemoryStream() )
{
int count = 0;
do
{
byte[] buf = new byte[1024];
count = stream.Read(buf, 0, 1024);
ms.Write(buf, 0, count);
} while(stream.CanRead && count > 0);
b = ms.ToArray();
}
редактировать:
Я проверил с помощью отражателя, и это вызов stream.Length, что не удается. GetResponseStream возвращает ConnectStream, а свойство Length этого класса выдает исключение, которое вы видели. Как упоминалось в других постерах, вы не можете надежно получить длину HTTP-ответа, так что это имеет смысл.
Вместо этого используйте StreamReader:
HttpWebRequest myReq = (HttpWebRequest)WebRequest.Create(url);
WebResponse myResp = myReq.GetResponse();
StreamReader reader = new StreamReader(myResp.GetResponseStream());
return reader.ReadToEnd();
(Примечание - выше возвращается String
вместо байтового массива)
Вы не можете достоверно запросить HTTP-соединение для его длины. Можно заставить сервер отправлять вам длину заранее, но (а) этот заголовок часто отсутствует и (б) он не гарантированно будет правильным.
Вместо этого вы должны:
- Создать фиксированную длину
byte[]
что вы передаетеStream.Read
метод - Создать
List<byte>
- После каждого чтения звоните
List.AddRange
добавить содержимое буфера фиксированной длины в список байтов
Обратите внимание, что последний звонок Read
вернет меньше, чем полное количество байтов, которые вы просили. Убедитесь, что вы добавляете только это количество байтов к вашему List<byte>
а не весь byte[]
, или вы получите мусор в конце вашего списка.
Если сервер не отправляет спецификацию длины в заголовке HTTP, размер потока неизвестен, поэтому вы получаете сообщение об ошибке при попытке использовать Length
имущество.
Читайте поток небольшими порциями, пока не достигнете конца потока.
С изображениями вам вообще не нужно читать количество байтов. Просто сделай это:
Image img = null;
string path = "http://www.example.com/image.jpg";
WebRequest request = WebRequest.Create(path);
req.Credentials = CredentialCache.DefaultCredentials; // in case your URL has Windows auth
WebResponse resp = req.GetResponse();
using( Stream stream = response.GetResponseStream() )
{
img = Image.FromStream(stream);
// then use the image
}
Возможно, вам следует использовать System.Net.WebClient
API. Если уже используете client.OpenRead(url)
использовать client.DownloadData(url)
var client = new System.Net.WebClient();
byte[] buffer = client.DownloadData(url);
using (var stream = new MemoryStream(buffer))
{
... your code using the stream ...
}
Очевидно, это загружает все до Stream
создан, поэтому он может победить цель использования Stream
, webClient.DownloadData("https://your.url")
получает массив байтов, который вы можете затем превратить в MemoryStream
,
Длина потока не может быть прочитана из потока, так как получатель не знает, сколько байтов отправит отправитель. Попробуйте поместить протокол поверх http и отправить, то есть длину, в качестве первого элемента в потоке.