Подтвердить что ты не робот

Ошибка "Этот поток не поддерживает операции поиска" в С#

Я пытаюсь получить изображение с 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;

Что я делаю с неправильными парнями?

4b9b3361

Ответ 1

Вероятно, вы хотите что-то подобное. Либо проверка длины терпит неудачу, либо 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, поэтому это имеет смысл.

Ответ 2

Используйте StreamReader вместо:

HttpWebRequest myReq = (HttpWebRequest)WebRequest.Create(url);
WebResponse myResp = myReq.GetResponse();

StreamReader reader = new StreamReader(myResp.GetResponseStream());
return reader.ReadToEnd();

(Примечание - выше приведена String вместо массива байтов)

Ответ 3

Вы не можете запросить HTTP-соединение по своей длине. Возможно, сервер заблаговременно отправит вам длину, но (а) этот заголовок часто отсутствует и (б) он не гарантированно будет правильным.

Вместо этого вы должны:

  • Создайте фиксированную длину byte[], которую вы передаете методу Stream.Read
  • Создайте List<byte>
  • После каждого чтения вызовите List.AddRange, чтобы добавить содержимое буфера с фиксированной длиной в свой список байтов.

Обратите внимание, что последний вызов Read будет возвращать меньше, чем полное количество байтов, которые вы просили. Убедитесь, что вы добавили только количество байтов на ваш List<byte>, а не весь byte[], или вы получите мусор в конце списка.

Ответ 4

Если сервер не отправляет спецификацию длины в заголовке HTTP, размер потока неизвестен, поэтому вы получаете ошибку при попытке использовать свойство Length.

Прочитайте поток в меньших кусках, пока не достигнете конца потока.

Ответ 5

Длина потока не может быть прочитана из потока, поскольку получатель не знает, сколько байтов отправит отправитель. Попробуйте поместить протокол поверх http и отправить, то есть длину как первый элемент в потоке.

Ответ 6

С изображениями вам не нужно читать количество байтов вообще. Просто сделайте следующее:

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
}

Ответ 7

Возможно, вам следует использовать 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.