How to upload files to Amazon S3 with Meteor?

2020-05-23 08:35发布

I'm trying to upload files to my Amazon S3 Bucket. S3 and amazon is set up. This is the error message from Amazon:

Conflicting query string parameters: acl, policy

Policy and signature is encoded, with Crypto.js for Node.js

var crypto=Npm.require("crypto");

I'm trying to build POST request with Meteor HTTP.post method. This could be wrong as well.

    var BucketName="mybucket";
    var AWSAccessKeyId="MY_ACCES_KEY";
    var AWSSecretKey="MY_SECRET_KEY";

    //create policy
    var POLICY_JSON={
        "expiration": "2009-01-01T00:00:00Z",
            "conditions": [ 
            {"bucket": BucketName}, 
            ["starts-with", "$key", "uploads/"],
            {"acl": 'public-read'},
            ["starts-with", "$Content-Type", ""],
            ["content-length-range", 0, 1048576],
        ]   
    }
    var policyBase64=encodePolicy(POLICY_JSON);
    //create signature
    var SIGNATURE = encodeSignature(policyBase64,AWSSecretKey);
    console.log('signature: ', SIGNATURE);

This is the POST request I'm using with Meteor:

    //Send data----------
    var options={
        "params":{
            "key":file.name,
            'AWSAccessKeyId':AWSAccessKeyId,
            'acl':'public-read',
            'policy':policyBase64,
            'signature':SIGNATURE,
            'Content-Type':file.type,
            'file':file,
            "enctype":"multipart/form-data",
        }
    }

    HTTP.call('POST','https://'+BucketName+'.s3.amazonaws.com/',options,function(error,result){
        if(error){
            console.log("and HTTP ERROR:",error);
        }else{
            console.log("result:",result);
        }
    });

and her I'm encoding the policy and the signature:

encodePolicy=function(jsonPolicy){
    // stringify the policy, store it in a NodeJS Buffer object
    var buffer=new Buffer(JSON.stringify(jsonPolicy));
    // convert it to base64
    var policy=buffer.toString("base64");
    // replace "/" and "+" so that it is URL-safe.
    return policy.replace(/\//g,"_").replace(/\+/g,"-");
}

encodeSignature=function(policy,secret){
    var hmac=crypto.createHmac("sha256",secret);
    hmac.update(policy);
    return hmac.digest("hex");
}

A can't figure out whats going on. There might already be a problem at the POST method, or the encryption, because I don't know these methods too well. If someone could point me to the right direction, to encode, or send POST request to AmazonS3 properly, it could help a lot.
(I don't like to use filepicker.io, because I don't want to force the client to sign up there as well.)

Thanks in advance!!!

4条回答
别忘想泡老子
2楼-- · 2020-05-23 09:10

Why don't you use the aws-sdk package? It packs all the needed methods for you. For example, here's the simple function for adding a file to bucket:

s3.putObject({
  Bucket: ...,
  ACL: ...,
  Key: ...,
  Metadata: ...,
  ContentType: ...,
  Body: ...,
}, function(err, data) {
  ...
});
查看更多
ゆ 、 Hurt°
3楼-- · 2020-05-23 09:12

Direct uploads to S3 you can use the slingshot package:

meteor add edgee:slingshot

On the server side declare your directive:

Slingshot.createDirective("myFileUploads", Slingshot.S3Storage, {
  bucket: "mybucket",
  allowedFileTypes: ["image/png", "image/jpeg", "image/gif"],

  acl: "public-read",

  authorize: function () {
    //You can add user restrictions here
    return true;
  },

  key: function (file) {
    return file.name;
  }
});

This directive will generate policy and signature automatically.

And them just upload it like this:

var uploader = new Slingshot.Upload("myFileUploads");

uploader.send(document.getElementById('input').files[0], function (error, url) {
  Meteor.users.update(Meteor.userId(), {$push: {"profile.files": url}});
});
查看更多
爱情/是我丢掉的垃圾
4楼-- · 2020-05-23 09:12

check out the S3 meteor package. The readme has a very comprehensive walkthrough of how to get started

查看更多
ゆ 、 Hurt°
5楼-- · 2020-05-23 09:19

First thing is to add the package for s3 file upload.

For Installation: ADD (AWS SDK Smart Package) $ meteor add peerlibrary: aws-sdk

1.Create Directive upload.js and paste this code.

angular.module('techno')
.directive("fileupload", [function () {
    return {
        scope: {
            fileupload: "="
        },
        link: function(scope,element, attributes){
            $('.button-collapse').sideNav();
            element.bind("change", function (event) {
                scope.$apply(function () {
                 scope.fileupload = event.target.files[0];
             });
           })
       }};
}]);

2.Get Access key and paste it in your fileUpload.js file.

AWS.config.update({
accessKeyId: ' AKIAJ2TLJBEUO6IJLKMN ',
secretAccessKey: lqGE9o4WkovRi0hCFPToG0B6w9Okg/hUfpVr6K6g'
});

AWS.config.region = 'us-east-1';
let bucket = new AWS.S3();

3.Now put this upload code in your directive fileUpload.js

vm.upload = (Obj) =>{
vm.loadingButton = true;
let name = Obj.name;
let params = {
    Bucket: 'technodheeraj',
    Key: name,
    ContentType: 'application/pdf',
    Body: Obj,
    ServerSideEncryption: 'AES256'
};

bucket.putObject(params, (err, data) => {
    if (err) {
        console.log('---err------->', err);
    }
    else {
        vm.fileObject = {
            userId: Meteor.userId(),
            eventId: id,
            fileName: name,
            fileSize: fileObj.size,
        };
   vm.call("saveFile", vm.fileObject, (error, result) => {
            if (!error){
                console.log('File saved successfully');

            }
        })
    }
})

};

4.Now in “saveFile” method paste this code

saveFile: function(file){
if(file){
    return Files.insert(file);
}

};

5.In HTML paste this code

<input type="file" name="file" fileupload="file">
<button type="button" class="btn btn-info " ng-click="vm.upload(file)"> Upload File</button>
查看更多
登录 后发表回答