1

我正在用 C# 编写一个 ASP.NET 服务器,它需要从外部服务器获取一堆图像。我遇到的问题是图像是从我的方法返回的,但看起来它们只加载了一半。

这是通过我的服务器加载磁贴时的样子(它是 OSM 循环地图磁贴):

瓷砖.png

如果我只是在浏览器中打开它(当然来自同一个 URL),这就是它的样子:

5.png

我很清楚所有字节都没有通过网络传输,但我不确定它们在哪里丢失。这就是我的代码的样子:

private byte[] GetTile(string url)
{
    var response = WebRequest.Create(url).GetResponse();

    Stream respStr = response.GetResponseStream();

    byte[] buf = new byte[response.ContentLength];
    respStr.Read(buf, 0, buf.Length);

    return buf;
}

这也不是正确的方法。我的字节去哪儿了?在我从函数返回之前,是否有推荐的方法来等待来自服务器的所有字节到达?

4

2 回答 2

4

respStr.Read(buf, 0, buf.Length);Read 不保证它会读取buf.Length字节。你应该检查它的返回值。或者简单地说,您可以使用将其复制到另一个流CopyTo

private byte[] GetTile(string url)
{
    var response = WebRequest.Create(url).GetResponse();

    Stream respStr = response.GetResponseStream();

    MemoryStream m = new MemoryStream();
    respStr.CopyTo(m);

    return m.ToArray();
}

您也可以为此使用WebClient

private byte[] GetTile(string url)
{
    using (WebClient wc = new WebClient())
    {
        return wc.DownloadData(url);
    }
}
于 2012-11-05T00:06:53.920 回答
1

我只是在模仿 Jon Skeet 的回答,因为它直接适用于您的问题。从流中创建字节数组

也许如果有人搜索类似的关键字,这个答案可以为他们指明正确的方向。你不是第一个也绝对不会是最后一个遇到这个问题的人。

Stream.Read()方法不保证将在 Stream 中读取所有字节,这在引用网络流时尤其明显。您需要确保检查返回值以绝对确定整个流已被消耗:

public static byte[] ReadFully(Stream input)
{
    byte[] buffer = new byte[16*1024];
    using (MemoryStream ms = new MemoryStream())
    {
        int read;
        while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
        {
            ms.Write(buffer, 0, read);
        }
        return ms.ToArray();
    }
}
于 2012-11-05T00:02:15.187 回答