0

I have a problem and stuck with how to upload 2 image different 2 folder with NodeJs Multer? I use s3 AWS service to upload my image to bucket

My route code:

const { s3Service } = require('../../services')

module.exports = (req, res, next) => {
  const controller = new Controller()
  const router = new express.Router()

  router.route('/createEvent').post(
    s3Service.upload.single('image'),
    controller.createEvent
  )

My multer code:

const multer = require('multer')
const AWS = require('aws-sdk')
const fs = require('fs')
const s3 = new AWS.S3({
  accessKeyId: process.env.BUCKET_ACCESSKEYID,
  secretAccessKey: process.env.BUCKET_SECRETACCESSKEY,
  endpoint: process.env.BUCKET_ENDPOINT
})

const storage = multer.diskStorage({
  filename: function (req, file, cb) {
    let filename = file.originalname
    filename = filename.replace(/ /g, '-')
    cb(null, 'event' + '-' + Date.now() + '-' + filename)
  }
})

const upload = multer({
  storage
})

const uploadToBucket = (fileContent, folderName, fileName, fileType) => {
  const params = {
    Bucket: process.env.BUCKET_NAME,
    Key: folderName + '/' + fileName,
    Body: fs.createReadStream(fileContent),
    ContentType: fileType,
    ACL: 'public-read'
  }

  s3.upload(params, (err, data) => {
    if (err) {
      console.log(err)
    }
    if (data) {
      fs.unlinkSync(fileContent)
      const url = data.Location
      console.log(url)

      return url
    }
  })
}

And my controller create function:

      const path = req.file.path
      s3Service.uploadToBucket(path, 'events', req.file.filename, req.file.mimetype)
      payload.image = {
        name: req.file.filename,
        url: process.env.BUCKET_EVENTSTORAGE + req.file.filename,
        type: req.file.mimetype,
        size: req.file.size
      }

      const data = await Event.create(payload)

I have already have upload 1 image, but i need to upload another image called certificate only if eventCertified have value true. I stuck and never try that before.

Yunnosch
  • 26,130
  • 9
  • 42
  • 54
ASHafizullah
  • 603
  • 1
  • 9
  • 22
  • Please do not edit solution announcements into the question. Accept (i.e. click the "tick" next to it) one of the existing answer, if there are any. You can also create your own answer, and even accept it, if your solution is not yet covered by an existing answer. Compare https://stackoverflow.com/help/self-answer – Yunnosch Dec 22 '22 at 01:33

1 Answers1

0

With multer, normally to handle multiple files you just have to change

from

const upload = multer({
  storage
})

to

const max_files_limit=2 // whatever that meets your need
const upload = multer({storage}).array('images',max_files_limit); // 'images', the first parameter, should be the name of your fields in the HTML form,etc

// In your code it should be like this I suppose
s3Service.upload.array('images',max_files_limit)

You can find multiple references here and there for examples.

After the multer middleware upload your files, the req object will have the files property on it.

You can access the mutiple files simply like that

const files = req.files // simply use req.files to retreive all your files
const events_promises=[]
for(let i=0;i<req.files.length;i++){
      s3Service.uploadToBucket(files[i].path, 'events', files[i].filename, files[i].mimetype)
      payload.image = {
        name: files[i].filename,
        url: process.env.BUCKET_EVENTSTORAGE + files[i].filename,
        type: files[i].mimetype,
        size: files[i].size
      }
      events.push(Event.create(payload)) // put all your promises / async in an array
      }
      
let events_result=Promise.all(events); // wait for all your promises to finish at once
await events_result // or events_result.then("something else");

I tried to follow your code logic, but I didn't test it or mock it, so sorry if there is some typo or unexpected error. In my example I put all the promises Event.create() in an array, to await on all the promises at once, if one Event create fail, the code in the example won't catch it propely.

Hope it helps

Loulou BadWeed
  • 146
  • 1
  • 6