使用HttpWebRequest下载后,PNG文件显示为红色问号

时间:2017-03-24 23:48:13

标签: c# rest unity3d unity5

我遇到以下问题:我从谷歌驱动器下载了一个png文件,所有字节都成功收到(看起来像),但是当我尝试构建Texture2D并将其设置为Sprite时在Image中,只显示红色问号。

我错过了什么吗?

以下代码:

HttpWebRequest request = (HttpWebRequest) WebRequest.Create("https://content.googleapis.com/drive/v3/files/" + fileId + "?alt=media");
request.Method = "GET";
request.ContentType = "image/png";
request.Headers.Add("Authorization", "Bearer " + AUTH_TOKEN);

WebResponse response = request.GetResponse();
byte[] bytes = new byte[response.ContentLength];
response.GetResponseStream().Read(bytes, 0, (int) response.ContentLength);
response.Close();

Texture2D texture2d = new Texture2D(8, 8);
Sprite sprite = null;
if (texture2d.LoadImage(bytes)) {
    sprite = Sprite.Create(texture2d, new Rect(0, 0, texture2d.width, texture2d.height), Vector2.zero);
}
if (sprite != null) {
    imageToUpdate.sprite = sprite;
}

2 个答案:

答案 0 :(得分:2)

我使用您的确切代码和image进行了快速测试,然后执行此操作:

问题是您下载所有图像字节。这不是如何使用HttpWebRequest下载所有图像字节。在while循环中使用MemoryStreamStream.Read。如果没有其他内容可供阅读,Stream.Read将返回0

请查看downloadFullData函数,了解如何正确执行此操作:

public Image imageToUpdate;

void Start()
{
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://wallpaper-gallery.net/images/hq-images-wallpapers/hq-images-wallpapers-12.jpg");
    request.Method = "GET";
    //request.ContentType = "image/png";
    //request.Headers.Add("Authorization", "Bearer " + AUTH_TOKEN);

    WebResponse response = request.GetResponse();

    if (response == null)
    {
        return;
    }

    //Download All the bytes
    byte[] bytes = downloadFullData(request);

    //Load Image
    Texture2D texture2d = new Texture2D(8, 8);
    Sprite sprite = null;
    if (texture2d.LoadImage(bytes))
    {
        sprite = Sprite.Create(texture2d, new Rect(0, 0, texture2d.width, texture2d.height), Vector2.zero);
    }
    if (sprite != null)
    {
        imageToUpdate.sprite = sprite;
    }
}

byte[] downloadFullData(HttpWebRequest request)
{
    using (WebResponse response = request.GetResponse())
    {

        if (response == null)
        {
            return null;
        }

        using (Stream input = response.GetResponseStream())
        {
            byte[] buffer = new byte[16 * 1024];
            using (MemoryStream ms = new MemoryStream())
            {
                int read;
                while (input.CanRead && (read = input.Read(buffer, 0, buffer.Length)) > 0)
                {
                    ms.Write(buffer, 0, read);
                }
                return ms.ToArray();
            }
        }
    }
}

<强>结果

这应该有效,但不要使用HttpWebRequest因为它会阻止您的程序直到下载图像。如果您想使用它,则必须在另一个Thread中使用它。这在这里变得非常复杂,因为您无法在另一个Thread中使用Unity的API,并且必须使用类似this的内容来调用Unity的API({{ 1}})在另一个线程中。

使用Unity的WWWUnityWebRequest API。下面的示例将使用texture2d.LoadImage(bytes)完成同样的事情。

UnityWebRequest

答案 1 :(得分:0)

您可能会收到错误响应或中间页面,这会使纹理无效。尝试通过两种方式检查收到的数据是否真的是有效的PNG图片:

  1. 通过System.IO.File.WriteAllBytes(path, bytes)将其导出到图像文件。
  2. 将前四个字节与the PNG header进行比较:

    //0x89, 'P', 'N', 'G'
    public static readonly byte[] PngHeaderBytes =
    {
        0x89, 0x50, 0x4E, 0x47
    };
    
  3. 另见red question mark loading image as texture with WWW