2

i need a help on how to upload multiple files image on amazon S3. i let's say that i have three input like this

<template lang="html">
 <form enctype="multipart/form-data" @submit.prevent="sendFile">
  <input type="file" ref="file1" @change="selectFile1">
  <input type="file" ref="file2" @change="selectFile2">
  <input type="file" ref="file3" @change="selectFile3">
  <div class="field">
   <button class="button is-info">Send</button>
  </div>
 </form>
</template>

and my frontend vue script looks like this

<script>
 import _ from 'lodash'

 export default {
  name: 'BulkUpload',



data() {
    return {
      file: "",
      message: "",
      error: false,
      sendFiles: []
    }
  },

  methods: {
    selectFile1() {
      this.file = this.$refs.file1.files[0]
      this.sendFiles.push(this.file)
      console.log(this.sendFiles);
    },

    selectFile2() {
      this.file = this.$refs.file2.files[0]
      this.sendFiles.push(this.file)
      console.log(this.sendFiles);
    },

    selectFile3() {
      this.file = this.$refs.file3.files[0]
      this.sendFiles.push(this.file)
      console.log(this.sendFiles);
    },

    sendFile() {

      let formData = new FormData()
      _.forEach(this.uploadFiles, file => {
        formData.append('file', file)
      })

      var self = this
      axios.post('http://localhost:3000/image/bulkupload', formData)
      .then(function(response) {
        console.log(response);
        self.message = "File has been uploaded"
        self.file = ""
        self.error = false
      })
      .catch(function(err) {
        self.message = "Something went wrong"
        self.error = true
        console.log(err);
      })
    }
  }
}
</script>

after sending it in using formData to the express server, my image route will handle it with this code

const sendingImage = require('../helper/sendingImage');

    router.post('/bulkupload', sendingImage.upload.array("file"), (req, res) => {
  var promises=[];
  for(var i = 0; i < req.files.length; i++) {
    var file = req.files[i];
    promises.push(sendingImage.uploadLoadToS3(file));
  }
  Promise.all(promises).then(function(data){
    res.send('Uploadedd');
    console.log('success');
  }).catch(function(err) {
    console.log('failed');
    res.send(err.stack);
  })
})

and my helper looks like this

const multer = require('multer');
const aws = require('aws-sdk');

aws.config.update({
  accessKeyId: <my access id>,
  secretAccessKey: <my secret key>
})

const upload = multer({
  dest: './uploads/'
})

function uploadLoadToS3(ObjFile){
  var params = {
    ACL :'public-read',
    Body : new Buffer(ObjFile.buffer),
    Bucket:'vue-express-upload',
    ContentType:ObjFile.mimetype,
    Key:ObjFile.originalname
  }
  return s3.upload(params).promise();
}

module.exports = {
  upload,
  uploadLoadToS3
}

to be honest, my code works without any problem. it send response status 200 without any error. but the problem is, when i check my S3 bucket, it doesn't have any uploaded file in it. it's still empty. is there anything wrong with my code ?

cantdocpp
  • 350
  • 7
  • 18

1 Answers1

1

The solution I found for using aws-sdk. The good that I will also use this solution and my projects.

Credits: StackOver - Answer Reference: Multer-s3

In your helper file you'll leave it like this:

const aws = require('aws-sdk')
const multer = require('multer')
const multerS3 = require('multer-s3')

aws.config = new aws.Config({
    accessKeyId: <my access id>,
    secretAccessKey: <my secret key>,
    region: <my region>
})
const s3 = new aws.S3()
const upload = multer({
    storage: multerS3({
    s3: s3,
    acl: 'public-read',
    bucket: 'vue-express-upload',
    contentType: function(req, file,cb){
        cb(null, file.mimetype)
    },
    key: function (req, file, cb) {
        cb(null, file.originalname)
    }
    })
})

module.exports = upload

The key of the file you can also change to something more unique, like the date / minutes / seconds. It is at your discretion, I used the filename as key.

In your router the route will look like this:

const upload = require('../helper/sendingImage')

router.post('/bulkupload', upload.array('files'), (req, res) => {
    console.log('success')
    //console.log(req.files)
    res.send('Uploadedd')
    //res.send(req.files)    
})

To view upload data:

router.post('/bulkupload', upload.array('files'), (req, res) => {
    res.send({
        status: 200,
        data: {
            sucess: true,
            file: req.files
        }
    })   
})

If there is no middleware file, it simply will not send. Will not return error. The only errors that can return are those of AWS access information.

Note:I used the postman.

Chance
  • 1,497
  • 2
  • 15
  • 25
  • i couldn't find the "../config/aws-config.json" in my helper. it give an output of "Cannot find module '../config/aws-config.json'". where do you find your config folder in express ? – cantdocpp Aug 29 '18 at 04:29
  • and by the way, if i don't require that aws-config.json, it give an error of "Missing credentials in config" – cantdocpp Aug 29 '18 at 04:31
  • A yes, but you have to put your credentials in aws.config. You can remove the aws-config.json require and put your direct access settings in aws.config. – Chance Aug 29 '18 at 16:11
  • I have edited the post, can remove the aws-config import and in place of aws.config put your aws credentials. – Chance Aug 29 '18 at 16:48
  • thank's man, it works. so after that we could save the image link to the mongoose database right ? – cantdocpp Aug 29 '18 at 17:16
  • Yes, within `req.files[p].location` will be the public link, one advice I give is not working with public link, but private with URL signed for a certain time. As it is several files will be a list. – Chance Aug 29 '18 at 18:35
  • Anything we are there, if the answer satisfies your problem please check the answer as accepted as best please. =) – Chance Aug 29 '18 at 18:46