node.jsmernmulter

MulterError: File too large : How to Handle this error?


i am building a register functionality and uploading a profile image and sending it to backend. There multer handles it. The file size limit is set to 100kb. Everything works fine. But when i upload file larger than 100 kb , this error comes :

MulterError: File too large

But what i want is if this error comes , i simply want to send a response directly as :

res.status(400).json({error : "File size too large"})

i have handled this res already on frontend.

How to send this above response if multer gives me the file too large error?

my multer middleware code :

import multer from "multer";

const storage = multer.diskStorage({
    filename: function (req, file, callback) {
        callback(null, file.originalname);
    }
});

const upload = multer(
    { storage: storage ,
      limits: { fileSize: 1024 * 100 }
    }
);

export default upload

my route code :

router.post('/signup' , upload.single('image') , signup)

my signup controller code :

export const signup = async (req , res)=>{
   try {

    const {fullname , username , email , password} = req.body;
    const imageFile = req.file;
   const validate =  EmailValidator.validate(email);

   if(!validate){
    return res.status(400).json({error : "Please enter a Valid Email"});
   }

   const existingUser = await User.findOne({username});
   if (existingUser) {
    return res.status(400).json({error : "Username already Taken!"})
   }

   const existingEmail = await User.findOne({email});
   if (existingEmail) {
    return res.status(400).json({error : "Email already Exists!"})
   }

   if(password.length < 6){
    return res.status(400).json({error : "Password Must be atleast 6 letters Long !"})
   }

   const salt = await bcrypt.genSalt(10)
   const hashedPass = await bcrypt.hash(password , salt);

   const imageUpload = await cloudinary.uploader.upload(imageFile.path, { resource_type: "image" });

   const newUser = new User({
    username , 
    password : hashedPass ,
    fullname , 
    email ,
    profileImg : imageUpload.secure_url , 
    isAdmin : false
   });

   if (newUser) {
    generateTokenAndSetCookie(newUser._id , res);
    await newUser.save();

    return res.status(201).json({message : "User Created Successfully"});

   } else {
    return res.status(500).json({error : "Invalid User Data"});
   }

   } catch (error) {
    console.log(`Error in signup Controller : ${error.message}`);
    return res.status(400).json({error : "Internal Server Error"});
   }
}

Solution

  • You need to call it from the route handler/controller instead, as described in the docs: Error handling

    For example:

    Remove it from the route:

    router.post('/signup', signup);
    

    Now call it from the route handler, and then handle the error (read err.message or .code as per the Multer errors:

    const uploadImg = upload.single('image');
    
    export function signup(req, res) {
    
        uploadImg(req, res, function(err) {
    
            if (err instanceof multer.MulterError) {
                // A Multer error occurred when uploading.
                
                // read err as per https://github.com/expressjs/multer/blob/master/lib/multer-error.js
    
                if(err.code === 'LIMIT_FILE_SIZE') res.status(400).json({error : "File size too large"})
    
            } else if (err) {
                // An unknown error occurred when uploading.
            }
    
            // Everything went fine.
        })
    }