问题
I face the following issue: I downloading a png file from google drive, all bytes are successfully received (as it seems), but when I try to construct a Texture2D and set it as Sprite in an Image, only red a question mark appears.
Am I missing something?
Code below:
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;
}
回答1:
I did a quick test with your exact code and this image and go this:
The problem is that you are not downloading all the image bytes. This is not how to download all the image bytes with HttpWebRequest. Use MemoryStream and Stream.Read in a while loop. If there is nothing else to read, Stream.Read will return 0.
Look at the downloadFullData function for how to do this properly:
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();
}
}
}
}
Result:
This should work but don't use HttpWebRequest because it will block your program until image is downloaded. If you want to use it then you must use it in another Thread. This gets really complicated from here because you can't use Unity's API in another Thread and would have to use something like this to call Unity's API( texture2d.LoadImage(bytes) ) in another Thread.
Use Unity's WWW or UnityWebRequest API for this. The example below will accomplish the-same exact thing with UnityWebRequest.
public Image imageToUpdate;
void Start()
{
StartCoroutine(downloadImage());
}
IEnumerator downloadImage()
{
string authorization = authenticate("YourUserName", "YourPass");
string url = "http://wallpaper-gallery.net/images/hq-images-wallpapers/hq-images-wallpapers-12.jpg";
UnityWebRequest www = UnityWebRequest.Get(url);
//www.SetRequestHeader("AUTHORIZATION", authorization);
DownloadHandler handle = www.downloadHandler;
//Send Request and wait
yield return www.Send();
if (www.isError)
{
UnityEngine.Debug.Log("Error while Receiving: " + www.error);
}
else
{
UnityEngine.Debug.Log("Success");
//Load Image
Texture2D texture2d = new Texture2D(8, 8);
Sprite sprite = null;
if (texture2d.LoadImage(handle.data))
{
sprite = Sprite.Create(texture2d, new Rect(0, 0, texture2d.width, texture2d.height), Vector2.zero);
}
if (sprite != null)
{
imageToUpdate.sprite = sprite;
}
}
}
string authenticate(string username, string password)
{
string auth = username + ":" + password;
auth = System.Convert.ToBase64String(System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(auth));
auth = "Basic " + auth;
return auth;
}
回答2:
You may get an error response or an intermediate page which will make the texture invalid. Try checking if the data received is really a valid PNG picture in two ways:
- Export it to an image file via
System.IO.File.WriteAllBytes(path, bytes). Compare the first four bytes with the PNG header:
//0x89, 'P', 'N', 'G' public static readonly byte[] PngHeaderBytes = { 0x89, 0x50, 0x4E, 0x47 };
See also red question mark loading image as texture with WWW.
来源:https://stackoverflow.com/questions/43010898/png-file-displayed-as-red-question-mark-after-download-with-httpwebrequest