Last active
August 3, 2021 02:27
-
-
Save prnthp/20423d8c2ade8730849766b81ee16552 to your computer and use it in GitHub Desktop.
Super simple way to queue up files to be uploaded to your S3 bucket in Unity without relying on the AWS .NET APIs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Net; | |
using System.Threading; | |
using System.Security.Cryptography; | |
using System.Text; | |
using UnityEngine; | |
public class AWSUploadAsync : MonoBehaviour | |
{ | |
// Adapted from: | |
// https://medium.com/xrlo-extended-reality-lowdown/uploading-to-aws-from-unity-5e7de2c80fce | |
// TODO: Point this to your server | |
private const string awsBucketName = "bucketName"; | |
private const string awsAccessKey = "XXXXXXXXXXXXXXXXXXXX"; | |
private const string awsSecretKey = "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"; | |
private static string awsURLBaseVirtual = ""; | |
[SerializeField] | |
private bool disableUploads; | |
public bool Uploading { get; private set; } | |
public class Upload | |
{ | |
public Thread Thread { get; private set; } | |
public string FileName; | |
public string FilePath; | |
public bool Done { get; private set; } | |
public bool Fail { get; private set; } | |
private Queue<Upload> _uploads; | |
public void StartUpload() | |
{ | |
if (Thread == null) | |
{ | |
Debug.Log("Starting upload thread"); | |
Thread = new Thread(() => UploadFileToAWS3(FileName, FilePath)); | |
Thread.Start(); | |
} | |
} | |
private void UploadFileToAWS3(string fileName, string filePath) | |
{ | |
Done = false; | |
Fail = false; | |
// TODO: You may or may not need this. | |
// Thread.Sleep(1000); | |
string currentAWS3Date = | |
System.DateTime.UtcNow.ToString( | |
"ddd, dd MMM yyyy HH:mm:ss ") + | |
"GMT"; | |
string canonicalString = | |
"PUT\n\n\n\nx-amz-date:" + | |
currentAWS3Date + "\n/" + | |
awsBucketName + "/" + fileName; | |
UTF8Encoding encode = new UTF8Encoding(); | |
HMACSHA1 signature = new HMACSHA1(); | |
signature.Key = encode.GetBytes(awsSecretKey); | |
byte[] bytes = encode.GetBytes(canonicalString); | |
byte[] moreBytes = signature.ComputeHash(bytes); | |
string encodedCanonical = Convert.ToBase64String(moreBytes); | |
string aws3Header = "AWS " + | |
awsAccessKey + ":" + | |
encodedCanonical; | |
string URL3 = awsURLBaseVirtual + fileName; | |
var requestS3 = (HttpWebRequest)WebRequest.Create(URL3); | |
requestS3.Headers.Add("Authorization", aws3Header); | |
requestS3.Headers.Add("x-amz-date", currentAWS3Date); | |
byte[] fileRawBytes = File.ReadAllBytes(filePath); | |
requestS3.ContentLength = fileRawBytes.Length; | |
requestS3.Method = "PUT"; | |
requestS3.Timeout = 100000; | |
requestS3.KeepAlive = false; | |
Debug.Log("[Thread] Starting upload: " + fileName); | |
try | |
{ | |
using (var s3Stream = requestS3.GetRequestStream()) | |
{ | |
s3Stream.Write(fileRawBytes, 0, fileRawBytes.Length); | |
} | |
Debug.Log("[Thread] Sent bytes: " + | |
requestS3.ContentLength + | |
", for file: " + | |
fileName); | |
} | |
catch (Exception e) | |
{ | |
Debug.Log("[Thread] Upload failed." + e); | |
Fail = true; | |
} | |
requestS3.Abort(); | |
if (Fail) | |
{ | |
Done = false; | |
} | |
else | |
{ | |
Done = true; | |
} | |
} | |
} | |
void Start() | |
{ | |
// TODO: Point this to your AWS S3 bucket's location | |
awsURLBaseVirtual = "https://" + | |
awsBucketName + | |
".s3.us-west-2.amazonaws.com/"; | |
_uploads = new Queue<Upload>(); | |
} | |
public void UploadFile(string fileName, string filePath) | |
{ | |
if (disableUploads) | |
{ | |
return; | |
} | |
var upload = new Upload | |
{ | |
FileName = fileName, | |
FilePath = filePath | |
}; | |
_uploads.Enqueue(upload); | |
} | |
private void Update() | |
{ | |
if (_uploads.Count > 0) | |
{ | |
Uploading = true; | |
var latestUpload = _uploads.Peek(); | |
if (!latestUpload.Done && latestUpload.Thread == null) | |
{ | |
Debug.Log("Starting next upload in queue."); | |
latestUpload.StartUpload(); | |
} | |
if (latestUpload.Done) | |
{ | |
Debug.Log("Upload done."); | |
_uploads.Dequeue(); | |
} | |
if (latestUpload.Fail) | |
{ | |
Debug.Log("Upload failed, re-enqueueing"); | |
var oldUpload = _uploads.Dequeue(); | |
var newUpload = new Upload | |
{ | |
FileName = oldUpload.FileName, | |
FilePath = oldUpload.FilePath | |
}; | |
_uploads.Enqueue(newUpload); | |
} | |
} | |
else | |
{ | |
Uploading = false; | |
} | |
} | |
// Blocking call | |
private bool UploadFileToAWS3(string fileName, string filePath) | |
{ | |
string currentAWS3Date = | |
System.DateTime.UtcNow.ToString( | |
"ddd, dd MMM yyyy HH:mm:ss ") + | |
"GMT"; | |
string canonicalString = | |
"PUT\n\n\n\nx-amz-date:" + | |
currentAWS3Date + "\n/" + | |
awsBucketName + "/" + fileName; | |
UTF8Encoding encode = new UTF8Encoding(); | |
HMACSHA1 signature = new HMACSHA1(); | |
signature.Key = encode.GetBytes(awsSecretKey); | |
byte[] bytes = encode.GetBytes(canonicalString); | |
byte[] moreBytes = signature.ComputeHash(bytes); | |
string encodedCanonical = Convert.ToBase64String(moreBytes); | |
string aws3Header = "AWS " + | |
awsAccessKey + ":" + | |
encodedCanonical; | |
string URL3 = awsURLBaseVirtual + fileName; | |
WebRequest requestS3 = | |
(HttpWebRequest)WebRequest.Create(URL3); | |
requestS3.Headers.Add("Authorization", aws3Header); | |
requestS3.Headers.Add("x-amz-date", currentAWS3Date); | |
byte[] fileRawBytes = File.ReadAllBytes(filePath); | |
requestS3.ContentLength = fileRawBytes.Length; | |
requestS3.Method = "PUT"; | |
try | |
{ | |
Stream s3Stream = requestS3.GetRequestStream(); | |
s3Stream.Write(fileRawBytes, 0, fileRawBytes.Length); | |
Debug.Log("Sent bytes: " + | |
requestS3.ContentLength + | |
", for file: " + | |
fileName); | |
s3Stream.Close(); | |
} | |
catch (Exception e) | |
{ | |
return false; | |
} | |
return true; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Usage: