4

I'm using AWS Unity (v3.3.50.0): S3 SDK (AWSSDK.S3.3.3.5.4.unitypackage) downloaded from https://aws.amazon.com/mobile/sdk/. My Unity version is 5.5.1.

I want to download an image placed on S3 bucket, bucket is configured and can be downloaded. And I see the string as data in response.

But I cannot able to convert the returned StreamReader to UnityEngine.UI.Image.sprite OR UnityEngine.UI.RawImage.texture in S3 sample GetObject() function.

private void GetObject()
{
    ResultText.text = string.Format("fetching {0} from bucket {1}", SampleFileName, S3BucketName);
    Client.GetObjectAsync(S3BucketName, SampleFileName, (responseObj) =>
        {
            string data = null;
            var response = responseObj.Response;
            if (response.ResponseStream != null)
            {
                using (StreamReader reader = new StreamReader(response.ResponseStream))
                {
                    data = reader.ReadToEnd();
                }

                ResultText.text += "\n";
                ResultText.text += data;
            }
            Debug.Log("GetObject: " + data);
        });
}

help required regarding this :)

Images on S3 bucket are in PNG format. But in future JPG, JPEG format support have to enable.

Programmer
  • 121,791
  • 22
  • 236
  • 328
eagle
  • 567
  • 1
  • 6
  • 24

1 Answers1

7

StreamReader is used for text not binary data like the image you want to download. I can tell why you are using it and can't also tell why you perform Debug.Log("GetObject: " + data); on an image.

Download the image,then use Texture2D.LoadImage to convert it to Texture2D, you can then load that to your RawImage to display.

public RawImage displayTexture;

private void GetObject()
{
    ResultText.text = string.Format("fetching {0} from bucket {1}", SampleFileName, S3BucketName);
    Client.GetObjectAsync(S3BucketName, SampleFileName, (responseObj) =>
    {
        byte[] data = null;
        var response = responseObj.Response;
        if (response.ResponseStream != null)
        {
            using (StreamReader reader = new StreamReader(response.ResponseStream))
            {
                using (var memstream = new MemoryStream())
                {
                    var buffer = new byte[512];
                    var bytesRead = default(int);
                    while ((bytesRead = reader.BaseStream.Read(buffer, 0, buffer.Length)) > 0)
                        memstream.Write(buffer, 0, bytesRead);
                    data = memstream.ToArray();
                }
            }

            //Display Image
            displayTexture.texture = bytesToTexture2D(data);
        }
    });
}

public Texture2D bytesToTexture2D(byte[] imageBytes)
{
    Texture2D tex = new Texture2D(2, 2);
    tex.LoadImage(imageBytes);
    return tex;
}

Like I mentioned above, using StreamReader is not good for binary data. You can just use MemoryStream to do that. In that case, your new GetObject function should look like this:

private void GetObject()
{
    ResultText.text = string.Format("fetching {0} from bucket {1}", SampleFileName, S3BucketName);
    Client.GetObjectAsync(S3BucketName, SampleFileName, (responseObj) =>
    {
        byte[] data = null;
        var response = responseObj.Response;
        Stream input = response.ResponseStream;

        if (response.ResponseStream != null)
        {
            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);
                }
                data = ms.ToArray();
            }

            //Display Image
            displayTexture.texture = bytesToTexture2D(data);
        }
    });
}
Programmer
  • 121,791
  • 22
  • 236
  • 328
  • nice job. it worked! thanks! :) is there any performance optimize way to do it? as in this, first you are reading it, then writing it into buffer, then converting it to byte[]. Isn't there a way to convert stream directly to byte[]? – eagle Feb 15 '17 at 12:41
  • 1
    Nope. You don't know the size of the stream so that's the only way. Another way to do this is to not use Amazon service. Develop your own service with TCP protocol that will send the bytes count first then the bytes. In this case, you know the byte amount and will allocate memory once to download the image. – Programmer Feb 15 '17 at 12:45