ilia1
ilia1

Reputation: 121

NodeJS & Multer: stop uploading file if error occurs

hello i creating file upload with Node & Multer, it works but problem is that if error occur (like user did not fill other fields) it still uploads file which i don't want

i literally don't know what to do because i am doing it first time so wish if anyone got experience with this. here is my code

const storage = multer.diskStorage({

  destination: (req, file, callback) => {
    const userPath = path.join(imgStoragePath, req.userId);
    fs.mkdir(
      userPath,
      () => callback(null, userPath)
    )
  },

  filename: (req, file, callback) => {
    const filenameParts = file.originalname.split('.');
    const ext = filenameParts.pop();
    const basename = filenameParts.join('.');
    const additionalPath = Date.now() + '' + uuid() + '' +             
Math.floor(Math.random() * (2000 - 500)) + 500;
    callback(null, basename + '-' + additionalPath + '.' + ext);
  }

})

const upload = multer({
  storage,
  limits: '1mb'
})


   router.post('/', upload.single('image'), async (req, res) => {
  //code
})

if error occurs it should return error message and send it to server and stop code execution and don't do anything, it does it but also uploads file, i know this will happen because upload is middleware and middleware executes first and i want it to prevent it. Thanks!

Upvotes: 6

Views: 3815

Answers (2)

Jude Fernandes
Jude Fernandes

Reputation: 7517

Okay so multer is not really responsible for validating your form inputs, it's sole purpose is to allow you to upload a file to the backend. Now getting to the issue you're trying to solve

  • you could have html validation in the front end to make sure the user fills in all the required fields before submitting the form
  • you could make a backend check to make sure that all the required fields have been filled in

In order to use the 2nd step you can use a function like this

 export const setRequired = (...args: any): boolean => {
   let isValid = true;
   _.forEach(args, value => {
     if (isUndefined(value)) isValid = false;
   });
   return isValid;
 };
 const isValid: any = setRequired(file, first_name, last_name);

The function uses typescript and lodash and checks that all the parameters specified exist. So before you perform any operation in your backend, pass in the required fields to the function which will return a boolean to notify you if all the required fields have been received from the front end.

About the 2nd part related to file size and file type errors for multer, you can try something like this

 const storage = multer.diskStorage({
 destination(req, file, cb) {
   cb(null, path.join(__dirname, `path_to_folder`));
 },
 filename(req, file, cb) {
   const ext = path.extname(file.originalname).toLowerCase();
   const file_name = uuidv4() + "_" + ext;
   cb(null, file_name);
 },
});

const upload = multer({
 storage,
 limits: { fileSize: 2000000 }, // In bytes: 2000000 bytes = 2 MB
 fileFilter(req, file, cb) {
   const ext = path.extname(file.originalname).toLowerCase();
   if (ext !== ".png" && ext !== ".jpg" && ext !== ".jpeg") {
     cb(new Error("Error: Unacceptable file format"), false);
   } else {
     cb(null, true);
   }
 },
}).any();
  router.post("/", (req, res) => {
    upload(req, res, async err => {
      if (err) {
        console.error(err);
        // An unknown error occurred when uploading.
        // the err object will contain the reason for the multer error
      } 

      if (req.files && req.files[0]) {
        // file has been saved 
         console.log(req.files[0].filename);
      }

    });
  },
);

Upvotes: 3

vishnu prasath
vishnu prasath

Reputation: 112

 app.post('/upload',[
  multer({
    dest    : './uploads/',
    onError : function(err, next) {
      console.log('error', err);
      next(err);
    }
  }),
  function(req, res) {
    res.status(204).end();
  }
]);

//check out for this link from multer docs https://github.com/expressjs/multer#error-handling

Upvotes: 0

Related Questions