直接浏览器使用Meteor,jQuery和AWS SDK上传到S3

时间:2013-10-27 17:14:58

标签: jquery file-upload amazon-s3 meteor

我已经了解了这个主题的几乎所有资源,但仍然需要你的帮助来完成这项工作。我想直接从我的Meteor应用程序中的浏览器上传文件到我的S3。为此,我向客户提供了一个签名的URL,就像在这个简化的例子中一样:

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();
    }
}

客户端然后调用此方法,获取看起来像这样的签名网址

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

并尝试使用jQuery上传文件,如下所示:

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);
                }
            });
        }
    }
});

我想使用jQuery,因为我觉得这可能是一个很好的方式来涵盖很多浏览器和浏览器版本。我还检查了这个特定存储桶的CORS配置,它看起来像这样:

<?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中的对象。此外,如果我在私人文件上签署了GET调用的URL,则签名的URL是有效的。我可能在邮政电话上做错了。

非常感谢任何帮助!

3 个答案:

答案 0 :(得分:1)

为了实现这一目标,我必须在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 :(得分:0)

这里的问题相同 - 我认为这是因为Meteor在应用程序头中不允许使用CORS。我也在努力解决这个问题。

答案 2 :(得分:0)

问题可能是您为PUT请求请求SignedUrl,但稍后您将文件POST到S3。您应该将文件输入S3而不是POST。

SignedUrls现在只允许GET和PUT。

有关详细信息,请参阅此答案:upload-file-from-angularjs-directly-to-amazon-s3-using-signed-url