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

使用Meteor、jQuery和AWS SDK将浏览器直接上传到S3,jquery,file-upload,amazon-s3,meteor,Jquery,File Upload,Amazon S3,Meteor,我已经了解了这个主题的几乎所有资源,但仍然需要您的帮助来完成这项工作。我想直接上传文件到我的S3直接从浏览器在我的流星应用程序。为此,我向客户端提供了一个签名url,如下面的简化示例所示: Meteor.methods({ requestUpload: function(filename) { var fut = new Future(); new Fiber(function() { var params = {

我已经了解了这个主题的几乎所有资源,但仍然需要您的帮助来完成这项工作。我想直接上传文件到我的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();
    }
}
然后,客户端调用此方法,获取签名的url,如下所示

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

并尝试使用jQuery上传带有POST请求的文件,如以下代码段所示:

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);
                }
            });
        }
    }
});
Template.form.events({
“提交表单”:函数(e,t){
e、 预防默认值();
var fileInput=t.find(“输入[type=file]”);
对于(var i=0;i
我想使用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>

*
邮递
放
3000
*
我在服务器上配置SDK时使用的凭据被确保是正确的,它们具有管理权限,我一直在使用它们从服务器将对象放入S3并从中获取对象。此外,如果我为私有文件上的GET调用签名了url,那么签名的url是有效的。我可能是在电话留言上做错了什么


非常感谢您的帮助

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

为了让它正常工作,我必须向
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();
    }
}

问题可能是您为PUT请求请求SignedUrl,但稍后会将文件发布到S3。你应该把文件放到S3而不是POST

SignedUrls现在只允许GET和PUT

有关更多信息,请参阅以下答案: