0

I am using multer and multer-s3 to upload an image to s3 bucket.

I want to keep the original image as it is, but need additional thumbnail image. Then upload both of them to s3. I found that image resize can be done using sharp but not sure how to do this particular task.

Can anyone advice how to do this ?

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

aws.config.update({
    secretAccessKey: process.env.AWSSecretKey,
    accessKeyId: process.env.AWSAccessKeyId,
});

const s3 = new aws.S3();

const fileFilter = (req, file, cb) => {
    if (file.mimetype === "image/jpeg" || file.mimetype === "image/png") {
        cb(null, true);
    } else {
        cb(new Error("Invalid file type, only JPEG and PNG is allowed!"), false);
    }
};

const storage = multerS3({
    s3: s3,
    bucket: process.env.S3_Bucket_Name,
    acl: 'public-read',
    metadata: (req, file, cb) => {
        cb(null, {
            fieldName: file.fieldname
        });
    },
    key: (req, file, cb) => {
        cb(null, Date.now().toString())
    }

});

const upload = multer({
    fileFilter: fileFilter,
    storage: storage,
});

module.exports = upload;

Routing is done in following manner

router.post('/post/add', checkAuth, upload.single("photo"), PostController.createPost);
Janaka
  • 2,505
  • 4
  • 33
  • 57

2 Answers2

1

After you saved your image you can resize it easelie.

You just need to pass the path to the image.

Note here: You can get the width and height of the image and check if the image needs an resize.

const sharp = require("sharp");

async function resizeImage(req, res) {
   let { width, height } = await sharp("path/to/image").metadata();
   let resizedImage;
   // you can check here if the image is too big. I will resize it to an width of 400
   if(width > 400) {
      await sharp("path/to/image")
          .resize({ fit: sharp.fit.contain, width: 400 })
          .jpeg({ quality: 90 })
          .toFile("path/to/thumbnail/directory);
   }
}
bill.gates
  • 14,145
  • 3
  • 19
  • 47
  • I am not clear how to connect this function to my router.post. I am saving the actual size photo as upload.single("photo") How do I put this function into that chain? Not sure how to get the path to the image also. – Janaka Sep 04 '20 at 11:40
  • in your `PostController.createPost` you should be able to access your file with `req.file` try an `console.log(req.file)` you should also see the path – bill.gates Sep 04 '20 at 11:42
  • @Janaka before your `PostController.createPost` you could make a new middleware called `PostController.resizeImage` where you get the path out of the `req.file` object, resize it and then move to the next middleware with `next()` – bill.gates Sep 04 '20 at 11:43
  • I modified the post like this; router.post('/post/add', checkAuth, resizePhoto, upload.single("photo"), PostController.createPost); But inside resizePhoto req.file is undefined – Janaka Sep 04 '20 at 12:21
  • But upload.single("photo") does upload the photo to s3. I am really puzzled how upload.single("photo") pass the file – Janaka Sep 04 '20 at 12:23
  • @Janaka you cannot access `req.file` before your resize. – bill.gates Sep 04 '20 at 13:54
  • to resize the image, I have to get the file. So how do I pass the file to resizeImage. The file is passed in the post as form-data – Janaka Sep 04 '20 at 14:29
  • If I have the post like this; router.post('/post/add', checkAuth, resizePhoto, PostController.createPost); How do I access file in resizePhoto? – Janaka Sep 04 '20 at 14:30
  • 1
    `router.post('/post/add', checkAuth, upload.single("photo"),resizeImage, PostController.createPost);` would be the correct way. you are only able to access it AFTER the multer middleware – bill.gates Sep 04 '20 at 14:45
0

Try this, usage of sharpe module.Change route handler according to your needs

router.post(
  "/users/me/avatar",
  authMiddleware,
  upload.single("avatar"),
  async (req, res) => {
      const buffer = await sharpe(req.file.buffer)
        .png()
        .resize({
          width: 300,
          height: 300
        })
        .toBuffer();
      req.user.avatar = buffer;
      await req.user.save();
      res.send();
    },
Jatin Mehrotra
  • 9,286
  • 4
  • 28
  • 67