【问题标题】:Error "This stream does not support seek operations" in C#C# 中的错误“此流不支持查找操作”
【发布时间】:2011-03-26 22:17:24
【问题描述】:

我正在尝试使用 byte 流从 url 获取图像。但我收到此错误消息:

此流不支持查找操作。

这是我的代码:

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;

我做错了什么?

【问题讨论】:

标签: c# stream byte


【解决方案1】:

使用图像,您根本不需要读取字节数。只需这样做:

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
}

【讨论】:

    【解决方案2】:

    也许您应该使用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

    【讨论】:

      【解决方案3】:

      你可能想要这样的东西。检查长度失败,或者 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 响应的长度,所以这是有道理的。

      【讨论】:

      • 您好,ngoozeff,谢谢,成功了!似乎工作正常!
      • 流长度失败,但 response.ContentLength 返回有效长度。
      • 如果您想将其用作图像,则不需要像这样将其转换为字节。请参阅下面的答案。
      • 你不需要do { ... } ,你可以使用stream.CopyTo(ms);来代替。
      • 我使用此代码,但我的内存流抛出异常“readtimeout & writetimeout”也是我的流。 Canseek = false 我尝试了很多解决方案,但没有任何帮助
      【解决方案4】:

      改用StreamReader

      HttpWebRequest myReq = (HttpWebRequest)WebRequest.Create(url);
      WebResponse myResp = myReq.GetResponse();
      
      StreamReader reader = new StreamReader(myResp.GetResponseStream());
      return reader.ReadToEnd();
      

      (注意——上面返回的是String而不是字节数组)

      【讨论】:

      • (... 然后可以使用 Encoding 类提供的函数将其转换为字节数组。)
      • 如果它有关于如何从 StreamReader 获取它到字节或图像的例程或链接。如果没有这个,我会说,我们仍然处于第一阶段。这对我一点帮助都没有。
      【解决方案5】:

      您无法可靠地询问 HTTP 连接的长度。可以让服务器提前向您发送长度,但是 (a) 该标头经常丢失,并且 (b) 不能保证它是正确的。

      相反,您应该:

      1. 创建一个固定长度的byte[] 并传递给Stream.Read 方法
      2. 创建一个List<byte>
      3. 每次读取后,调用List.AddRange 将固定长度缓冲区的内容附加到字节列表中

      请注意,最后一次调用 Read 将返回少于您请求的完整字节数。确保您只将这些字节数附加到您的 List<byte> 而不是整个 byte[],否则您将在列表末尾得到垃圾。

      【讨论】:

      • 嗨,我现在有点困惑。那么我的代码应该是什么样子?
      • @Yustme, var buffer = new List<byte>(); while (true) { byte[] tmpBuffer = new byte[1024]; int bytesRead = br.Read(tmpBuffer, 0, tmpBuffer.length); buffer.AddRange(tmpBuffer.Take(bytesRead)); if (bytesRead < tmpBuffer.length) { break; } }
      【解决方案6】:

      如果服务器未在 HTTP 标头中发送长度规范,则流大小是未知的,因此在尝试使用 Length 属性时会出现错误。

      以较小的块读取流,直到到达流的末尾。

      【讨论】:

        【解决方案7】:

        无法从流中读取流的长度,因为接收方不知道发送方将发送多少字节。尝试将协议放在 http 之上并发送,即长度作为流中的第一项。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2014-06-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-09-11
          • 1970-01-01
          相关资源
          最近更新 更多