Как загрузить файлы на Amazon S3 с помощью Meteor?

Я пытаюсь загрузить файлы в свой ковш Amazon S3. S3 и amazon. Это сообщение об ошибке от Amazon:

Конфликтные параметры строки запроса: acl, policy

Политика и подпись кодируются с помощью Crypto.js для Node.js

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

Я пытаюсь создать запрос POST с помощью метода Meteor HTTP.post. Это может быть и неправильным.

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

Это запрос POST, который я использую с помощью 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);
        }
    });

и ее я кодирую политику и подпись:

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 не может понять, что происходит. Возможно, проблема может возникнуть в методе POST или в шифровании, потому что я слишком плохо знаю эти методы. Если кто-то может указать мне в правильном направлении, закодировать или отправить запрос POST на AmazonS3 правильно, это может сильно помочь.
(Я не люблю использовать filepicker.io, потому что я не хочу заставлять клиента также зарегистрироваться там.)

Спасибо заранее!

Ответ 1

Прямая загрузка на S3 вы можете использовать slingshot пакет:

meteor add edgee:slingshot

На стороне сервера объявите свою директиву:

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

Эта директива автоматически создаст политику и подпись.

И они просто загружают его вот так:

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

Ответ 2

Почему вы не используете пакет aws-sdk? Он содержит все необходимые методы для вас. Например, здесь простая функция для добавления файла в корзину:

s3.putObject({
  Bucket: ...,
  ACL: ...,
  Key: ...,
  Metadata: ...,
  ContentType: ...,
  Body: ...,
}, function(err, data) {
  ...
});

Ответ 3

проверьте S3 метеорный пакет. В readme есть очень подробное пошаговое руководство по началу работы.

Ответ 4

Прежде всего, нужно добавить пакет для загрузки файла s3.

Для установки: ADD (пакет AWS SDK Smart)  $ meteor add peerlibrary: aws-sdk

1.Создайте директиву upload.js и вставьте этот код.

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. Введите ключ доступа и вставьте его в свой fileUpload.js файл.

AWS.config.update({
accessKeyId: ' AKIAJ2TLJBEUO6IJLKMN ',
secretAccessKey: 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'
});

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

3.Вставьте этот код загрузки в свою директиву 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. Теперь в режиме "saveFile" вставьте этот код

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

};

5.В HTML вставьте этот код

<input type="file" name="file" fileupload="file">
<button type="button" class="btn btn-info " ng-click="vm.upload(file)"> Upload File</button>