Search code examples
node.jsmulter

How can i change the size of images with multer with sharp?


I built a web app and want to resize my images to be smaller for better quality to my profile pictures. I am using "multer" for upload picture and sharp package for resizing.

For some reason i get this error:

"[0] [Error: D:\DevConnectors\public\resized\5f4f4e0bb295ba36042536bf.jpg: unable to open for write
[0] windows error: The storage control block address is invalid."

My code:

const storage = multer.diskStorage({
  destination: (req, file, cb) => {
    cb(null, DIR)
  },
  filename: (req, file, cb) => {
    var typeFile = file.originalname.split(".").pop()
    const fileName = req.user.id + "." + typeFile
    cb(null, fileName)
  },
})

var upload = multer({
  storage: storage,
  fileFilter: (req, file, cb) => {
    if (
      file.mimetype == "image/png" ||
      file.mimetype == "image/jpg" ||
      file.mimetype == "image/jpeg"
    ) {
      cb(null, true)
    } else {
      return cb(new Error("Only .png, .jpg and .jpeg format allowed!"), false)
    }
  },
})

const Profile = require("../../moduls/Profile")
const User = require("../../moduls/User")

//@route GET/api/profile/me
//@desc Get current users profile
//@access Private

router.post(
  "/upload",
  [auth, upload.single("imageProfile")],
  async (req, res) => {
    try {
      console.log(req.file)
      const { filename: image } = req.file
      await sharp(req.file.path)
        .resize(150)
        .jpeg({ quality: 50 })
        .toFile(path.resolve(req.file.destination, "resized", image))

      fs.unlinkSync(req.file.path)

      const url = req.protocol + "://" + req.get("host")
      let user = await User.findById(req.user.id)
      const profile = await Profile.findOne({ user: req.user.id })
      //Update
      if (user) {
        user.avatar = url + "/public/" + req.file.filename
        await user.save()
        return res.json(profile)
      }
    } catch (err) {
      console.log(err)
    }
  }
)

This happens at this line :

path.resolve(req.file.destination,'resized',image))

What am i doing wrong? i am using sharp docs.


Solution

  • Try this Configuration of multer ( change it according to your needs)

    import multer from "multer";
    import sharpe from "sharp";
    
    const upload = multer({      //multer configuration
      //dest: "avatars",       //so that buffer is available in route handler
      limits: {
        fileSize: 1000000,
      },
      fileFilter(req, file, cb) {        // object method shorthand syntax
        if (!file.originalname.match(/\.(jpg|jpeg|png)$/)) { //.match for using regex b/w (//)
          return cb(new Error("Please upload a IMAGE"));
        }
        cb(undefined, true);
      },
    });
    

    handle sharp in your route handle like this.

    router.post(
               "path",
              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();
            },
            (error, req, res, next) => {
              //to tell express this how mutler/s error should be handled
              res.status(400).send({
                error: error.message,
              });
            }
        );