1

I have encountered with multer and uploading to S3: I am sending 5 images in the following way:

app.post(
    '/upload',
    upload.fields(
    [
        { name: 'image', maxCount: 1 },
        { name: 'image2', maxCount: 1 },
        { name: 'image3', maxCount: 1 },
        { name: 'image4', maxCount: 1 },
        { name: 'image5', maxCount: 1 }
    ]),
    (req, res, next) => {
    res.status(200).send('Files uploaded successfully.')
});

Using the following multer imlementation:

var upload = multer({
  storage: multerS3({
    s3: s3,
    bucket: myBucket,
    fileFilter: (res, file, callback) => {
        var ext = path.extname(file.originalname);
        if(ext !== '.png' && ext !== '.jpg' && ext !== '.jpeg') {
            res.status(400).send('Only images are allowed')
        }
        callback(null, true)
    },
    acl: 'public-read',
    contentType: multerS3.AUTO_CONTENT_TYPE,
    key: function (req, file, cb) {
        uuidFileName = uuidv4();
        fileNamesArray.push(uuidFileName);
        if (!file.originalname.match(/\.(jpg|jpeg|png|gif)$/)) {
            return cb(new Error('Only image files are allowed!'));
        }
        cb(null, uuidFolderName + '/' + uuidFileName + '.' + mime.getExtension(file.mimetype))
    }
  })
})

My problem is that when a client send the fifth image as PDF for example, 4 images has already been uploaded to S3. While deleting them and cancelling the whole process is un-efficient, Iv'e been looking into multer's multiple upload option but without success, and no promise it will actually prevent before uploading the first one.

Any ideas?

StackMaster
  • 359
  • 1
  • 5
  • 22
  • It will be a little bit off topic, but are you sure that your `fileFilter` function works properly? As I can see from the Multer's documentation, the first argument is `req`, not `res`. Please, take a look [here](https://github.com/expressjs/multer#filefilter). Anyway, you should use `return res.status(...)`. Without `return` statement your `callback` always will be fired. – Vladyslav Turak Aug 29 '18 at 14:36

1 Answers1

0

First, on the front-end part, you could specify which MIME type your upload button accepts with the accept attribute of input's tag.

On the back, you could use express-fileupload, get the mime-types or just the names of your files and return an error when they don't match.

Example :

const fileUpload = require('express-fileupload');
const customCheckFiles = (req, res, next) => {
   const fileNames = Object.keys(req.files).map(key => req.files[key].name);
   return fileNames.every(filename => !!filename.match(/\.(jpg|jpeg|png|gif)$/))
     ? next() // let multer do the job
     : res.status(400).json({error: "Wrong image formats"});
}

app.post(
    '/upload',
    fileUpload(),
    customCheckFiles
    upload.fields(
    [
        { name: 'image', maxCount: 1 },
        { name: 'image2', maxCount: 1 },
        { name: 'image3', maxCount: 1 },
        { name: 'image4', maxCount: 1 },
        { name: 'image5', maxCount: 1 }
    ]),
    (req, res, next) => {
    res.status(200).send('Files uploaded successfully.')
});

I didn't test the code, it just serves as an example.

Hope it helps,
Best regards

boehm_s
  • 5,254
  • 4
  • 30
  • 44