最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to upload files to Amazon S3 with Meteor? - Stack Overflow

programmeradmin0浏览0评论

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/',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!!!

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!!!

Share Improve this question edited Apr 25, 2014 at 14:45 Shantha Kumara 3,4214 gold badges41 silver badges52 bronze badges asked Oct 24, 2013 at 15:42 zalavarizalavari 83910 silver badges21 bronze badges 1
  • queryString is not the same as POST params, maybe you need to duplicate the two complained-about params on the GET url... – dandavis Commented Oct 24, 2013 at 16:13
Add a comment  | 

4 Answers 4

Reset to default 6

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

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

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

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>
发布评论

评论列表(0)

  1. 暂无评论