Error "This stream does not support seek operations" in C#

C#StreamByte

C# Problem Overview


I'm trying to get an image from an url using a byte stream. But i get this error message:

> This stream does not support seek operations.

This is my code:

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;

What am i doing wrong guys?

C# Solutions


Solution 1 - C#

You probably want something like this. Either checking the length fails, or the BinaryReader is doing seeks behind the scenes.

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();
}

edit:

I checked using reflector, and it is the call to stream.Length that fails. GetResponseStream returns a ConnectStream, and the Length property on that class throws the exception that you saw. As other posters mentioned, you cannot reliably get the length of a HTTP response, so that makes sense.

Solution 2 - C#

Use a StreamReader instead:

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

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

(Note - the above returns a String instead of a byte array)

Solution 3 - C#

You can't reliably ask an HTTP connection for its length. It's possible to get the server to send you the length in advance, but (a) that header is often missing and (b) it's not guaranteed to be correct.

Instead you should:

  1. Create a fixed-length byte[] that you pass to the Stream.Read method
  2. Create a List<byte>
  3. After each read, call List.AddRange to append the contents of your fixed-length buffer onto your byte list

Note that the last call to Read will return fewer than the full number of bytes you asked for. Make sure you only append that number of bytes onto your List<byte> and not the whole byte[], or you'll get garbage at the end of your list.

Solution 4 - C#

If the server doesn't send a length specification in the HTTP header, the stream size is unknown, so you get the error when trying to use the Length property.

Read the stream in smaller chunks, until you reach the end of the stream.

Solution 5 - C#

With images, you don't need to read the number of bytes at all. Just do this:

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 = resp.GetResponseStream() ) 
{
    img = Image.FromStream(stream);
    // then use the image
}

Solution 6 - C#

Perhaps you should use the System.Net.WebClient API. If already using client.OpenRead(url) use 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 ...
}

Obviously this downloads everything before the Stream is created, so it may defeat the purpose of using a Stream. webClient.DownloadData("https://your.url") gets a byte array which you can then turn into a MemoryStream.

Solution 7 - C#

The length of a stream can not be read from the stream since the receiver does not know how many bytes the sender will send. Try to put a protocol on top of http and send i.e. the length as first item in the stream.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionYustmeView Question on Stackoverflow
Solution 1 - C#ngoozeffView Answer on Stackoverflow
Solution 2 - C#JustinView Answer on Stackoverflow
Solution 3 - C#Tim RobinsonView Answer on Stackoverflow
Solution 4 - C#GuffaView Answer on Stackoverflow
Solution 5 - C#vapcguyView Answer on Stackoverflow
Solution 6 - C#James EshView Answer on Stackoverflow
Solution 7 - C#schoetbiView Answer on Stackoverflow