Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HTML 5 Amazon S3 Direct Uploader

I am looking for an HTML 5 AJAX library / framework for users to upload files directly to Amazon S3. The goal is to avoid uploading attachments to the web server (as the web server blocks when it transfer them to Amazon). My understanding is that this should be possible using XDomainRequest, but I can't figure out how.

I am running ruby-on-rails and wanted to assign the uploaded file a temporary name (using a UUID) that will be posted back to the web server so the file can later be renamed and integrated with paperclip.

Any ideas? Is this something jQuery can handle? Flash isn't an option for this project. Thanks!

Edit:

I managed to get a basic post working but am still have issues. I'm not exactly sure what headers are required, or how to encode the Amazon required parameters in the request (can I put them in the request header?). Here is my progress thus far:

const XMLHTTPFactories = [
  function () { return new XDomainRequest(); },
  function () { return new XMLHttpRequest(); },
  function () { return new ActiveXObject("Msxml2.XMLHTTP"); },
  function () { return new ActiveXObject("Msxml3.XMLHTTP"); },
  function () { return new ActiveXObject("Microsoft.XMLHTTP"); },
];

var xhr = null;

for (var i = 0; i < XMLHttpFactories.length; i++) {
    try { xhr = XMLHttpFactories[i](); break; } catch (exception) { continue; }
}

$(this).change(function () {

  for (var i = 0; i < this.files.length; i++) {
    var file = this.files[i];

    xhr.open(settings.method, settings.url, true);
    xhr.setRequestHeader("Cache-Control", "no-cache");
    xhr.setRequestHeader("Content-Type", "multipart/form-data");
    xhr.setRequestHeader("Access-Control-Allow-Origin", "*")
    xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
    xhr.setRequestHeader("X-File-Name", file.fileName);
    xhr.setRequestHeader("X-File-Size", file.fileSize);

    xhr.send(file);
  }

Edit:

After further updates, I've managed to get the following error:

XMLHttpRequest cannot load http://bucket.s3.amazonaws.com/. Origin http://local.app is not allowed by Access-Control-Allow-Origin.

I've uploaded a crossdomain.xml file that allows access from the wildcard (*) domain. Not sure how to continue...

Edit:

After having done more investigation, I'm starting to think that the JavaScript POST might not be possible to S3. Will I be required to post to an EC2 instance before doing a transfer? I might be able to secure a micro instance, but I'd prefer to go direct to S3 if possible! Thanks!

Edit:

I posted the question on the Amazon Forums and haven't received any feedback. For cross references the other post can be found here: https://forums.aws.amazon.com/message.jspa?messageID=206650#206650.

like image 788
Kevin Sylvestre Avatar asked Dec 22 '22 21:12

Kevin Sylvestre


2 Answers

You need to make the other side issue an Access-Control-Allow-Origin header. In you case the other side is Amazon S3 server. Unless they mention your domain in that header you won't be able to make any cross-site requests to them.

Amazon S3 now supports Cross Origin Resource Sharing and you can configure any of your S3 buckets for cross-domain access by adding one or more CORS rules to your bucket. Each rule can specify a domain that should have access to your bucket and a set of HTTP verbs you wish to allow.

like image 200
sanmai Avatar answered Jan 08 '23 13:01

sanmai


Today Amazon announces complete support for Cross-Origin Resource Sharing (CORS) in Amazon S3. You can now easily build web applications that use JavaScript and HTML5 to interact with resources in Amazon S3, enabling you to implement HTML5 drag and drop uploads to Amazon S3, show upload progress, or update content.

like image 43
VAAA Avatar answered Jan 08 '23 13:01

VAAA