2

I am trying to create a form that uploads my local files to my S3 bucket, but I'm a little confused as to where parts of the uploading logic should exist. I wanted to keep my POST route clean and reference the AWS logic that is housed in a separate file, but I'm a little confused as to what value should be used for the Body property for the params level and how I should reference this module when setting the completed upload URL to my database property at the fileAttachment line. Can anyone point me in the right direction?

Here is my aws-s3.js file:

module.exports = function() {

var path = require('path');
var async = require('async');
var fs = require('fs');
var AWS = require('aws-sdk');
var config = require(path.resolve(__dirname, '..', '..','./config/config.js'));

AWS.config.region = config.region;

var s3 = new AWS.S3({params: {Bucket: config.awsBucket}});

var params = {Key: config.awsAccessKeyId, Body: req.body.fileAttachment};

s3.upload(params, function(err, data){
    if (err) {
        console.log("Error uploading data: ", err);
    } else {
        console.log("Successfully uploaded data to " + config.awsBucket + " /myKey");

    }
});

return s3;

};

Here is my route:

appRoutes.route('/create/file')

    .get(function(req, res){
        models.DiscoverySource.findAll({
            where: {
                organizationId: req.user.organizationId
            }, attributes: ['discoverySource']
        }).then(function(discoverySource){
            res.render('pages/app/file-create.hbs',{
                discoverySource: discoverySource
            });
        });

    })



    .post(function(req, res){
        models.File.create({
            discovery: req.body.discovery,
            discoverySource: req.body.discoverySource,
            fileAttachment: 
            userId: req.user.user_id        
        }).then(function(){
            res.redirect('/app');
        });
    });

Form:

<form action="/app/create/file" method="post">
                <div class="form-header">
                    <label for="data-discovery-source">Discovery Source:</label>
                    <select name="discoverySource">
                        {{#each discoverySource}}
                        <option value="{{this.discoverySource}}">{{this.discoverySource}}</option>
                        {{/each}}
                    </select>
                    <label for="data-discovery">Discovery:</label>
                    <textarea id="discovery-text-field" name="discovery"></textarea>
                    <label for="report-link">File Attachment:</label>
                    <input type="file" name="fileAttachment">
                </div>
                <button type="submit" id="create-button">Create File</button>
            </form>

2 Answers 2

3

You can try using the multer-s3 module.

It allows you to upload your file with storaage configured to AWS.

This code uses the aws-sdk module and more about it's configuration can be found here.

Here is my code example:

It uses the recommended amazon AWS SDK for JavaScript in Node.js with And it also uses multer express middleware for uploading files.

var aws = require('aws-sdk')
var express = require('express')
var multer = require('multer')
var multerS3 = require('multer-s3')

var app = express()
var s3 = new aws.S3({ {accessKeyId: 'akid', secretAccessKey: 'secret'}) 
//this can also be configured in config file and through code



var upload = multer({
  storage: multerS3({
    s3: s3,
    bucket: 'some-bucket',
    key: function (req, file, cb) {
      cb(null, Date.now().toString())
    }
  })
})

//the upload.array -means that you can load multiple files(max 3) named photos maximum 3,  the resulting AWS full path urls will be returned in req.files 
app.post('/upload', upload.array('photos', 3), function(req, res, next) {
  //reference results that can be stored in database for example in req.files
  res.send('Successfully uploaded ' + req.files.length + ' files!')
})

this codealso uses the multer npm module. More about its configuration possibilities like: single, any upload.array, fields can be found here.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for sharing this, but there doesn't appear to be much documentation or overlap with my question. Where do I set my access key ID? What do the upload.array() parameters represent? How can I reference the resulting uploaded URL to my database fileAttachment?
Updated my answer.
2

You can alternatively use Minio-js here is an example of presigned-postpolicy.js. I hope it helps.

var Minio = require('minio')

var s3Client = new Minio({
  endPoint: 's3.amazonaws.com',
  accessKey: 'YOUR-ACCESSKEYID',
  secretKey: 'YOUR-SECRETACCESSKEY',
  insecure: false // Default is false.
})

// Construct a new postPolicy.
var policy = s3Client.newPostPolicy()
// Set the object name my-objectname.
policy.setKey("my-objectname")
// Set the bucket to my-bucketname.
policy.setBucket("my-bucketname")

var expires = new Date
expires.setSeconds(24 * 60 * 60 * 10) //10 days
policy.setExpires(expires)

policy.setContentLengthRange(1024, 1024*1024) // Min upload length is 1KB Max upload size is 1MB

s3Client.presignedPostPolicy(policy, function(e, formData) {
  if (e) return console.log(e)
  var curl = []
  curl.push('curl https://s3.amazonaws.com/my-bucketname')
  for (var key in formData) {
    if (formData.hasOwnProperty(key)) {
      var value = formData[key]
      curl.push(`-F ${key}=${value}`)
    }
  }
  // Print curl command to upload files.
  curl.push('-F file=@<FILE>')
  console.log(curl.join(' '))
}) 

Disclaimer: I work for Minio, Open Source object storage compatible with AWS S3.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.