Direct browser download on S3 using Meteor, jQuery and AWS SDK

I have almost every resource on this topic, but you still need your help to complete this work. I want to directly upload files to my S3 directly from a browser in my Meteor application. To do this, I provide the signed URL to the client, as in this simplified example:

Meteor.methods({
    requestUpload: function(filename) {
        var fut = new Future();
        new Fiber(function() {
            var params = {
                Bucket: MY_BUCKET,
                Key: new Date().getTime() + "_" + filename
            };
            var surl = s3.getSignedUrl('putObject', params, function(err, surl) {
                if (!err) {
                    console.log("signed url: " + surl);
                    fut.return(data);
                } else {
                    console.log("Error signing url " + err);
                    fut.return();
                }
            });
        }).run();
        return fut.wait();
    }
}

Then the client calls this method, gets the signed URL, which looks like this

https://mybucket.s3-eu-west-1.amazonaws.com/1382890365957_myfile.png?AWSAccessKeyId=AKBLABLA&Expires=1382891265&Signature=BLABLA

and trying to upload a file with a POST request using jQuery, as in this snippet:

Template.form.events({
    'submit form': function(e, t) {
        e.preventDefault();
        var fileInput = t.find("input[type=file]");
        for (var i = 0; i < fileInput.files.length; i++) {
            var file = fileInput.files[i];
            Meteor.call("requestUpload", file.name, function(err, surl) {
                if (!err) {
                    console.log("signed url: " + surl);
                    var reader = new FileReader();
                    reader.onload = function(event) {

                    // Here I am trying to upload, it fails
                        $.post(surl, reader.result, function(data, status) {
                            console.log("status: " + status);
                            console.log("data: " + data);
                        });
                    };
                    reader.readAsDataURL(file);
                } else {
                    console.log(err);
                }
            });
        }
    }
});

I want to use jQuery because I'm sure this is a good way to span many browsers and browser versions. I also checked my CORS configuration for this particular bucket, it looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
    <CORSRule>
        <AllowedOrigin>*</AllowedOrigin>
        <AllowedMethod>POST</AllowedMethod>
        <AllowedMethod>PUT</AllowedMethod>
        <MaxAgeSeconds>3000</MaxAgeSeconds>
        <AllowedHeader>*</AllowedHeader>
    </CORSRule>
</CORSConfiguration>

, SDK , , , S3 . , URL- GET , URL- . , , - .

!

+2
3

, s3.getSignedUrl:

ContentType: mimeType,
Body: '',
"ACL": 'public-read'

:

Meteor.methods({
    requestUpload: function(filename, mimeType) {
        var fut = new Future();
        new Fiber(function() {
            var params = {
                Bucket: MY_BUCKET,
                Key: new Date().getTime() + "_" + filename,
                ContentType: mimeType,
                Body: '',
                "ACL": 'public-read'
            };
            var surl = s3.getSignedUrl('putObject', params, function(err, surl) {
                if (!err) {
                    console.log("signed url: " + surl);
                    fut.return(surl);
                } else {
                    console.log("Error signing url " + err);
                    fut.return();
                }
            });
        }).run();
        return fut.wait();
    }
}
+1

- , - , Meteor CORS . .

0

The problem may be that you are requesting SignedUrl for the PUT request, but later using the POST file on S3. You must specify the S3 file, not the POST.

SignedUrls only allow GET and PUT.

See this answer for more details: upload-file-from-angularjs-directly-to-amazon-s3-using-signed-url

0
source

All Articles