How to validate file uploads in Node.js

Validating file uploads is critical for Node.js applications to prevent security vulnerabilities, malicious files, and storage abuse. As the creator of CoreUI with over 11 years of Node.js development experience since 2014, I’ve implemented secure file upload validation in countless enterprise systems. The most effective solution is to use Multer’s fileFilter option combined with file size limits and MIME type validation. This approach provides comprehensive validation before files are written to disk.

Use Multer’s fileFilter and limits to validate file uploads in Node.js.

const express = require('express')
const multer = require('multer')
const path = require('path')

const app = express()

const storage = multer.diskStorage({
  destination: (req, file, cb) => {
    cb(null, 'uploads/')
  },
  filename: (req, file, cb) => {
    const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9)
    cb(null, file.fieldname + '-' + uniqueSuffix + path.extname(file.originalname))
  }
})

const fileFilter = (req, file, cb) => {
  const allowedMimes = ['image/jpeg', 'image/png', 'image/gif', 'application/pdf']
  const allowedExts = /jpeg|jpg|png|gif|pdf/

  const mimetype = allowedMimes.includes(file.mimetype)
  const extname = allowedExts.test(path.extname(file.originalname).toLowerCase())

  if (mimetype && extname) {
    return cb(null, true)
  }

  cb(new Error(`Invalid file type. Only ${allowedMimes.join(', ')} are allowed`))
}

const upload = multer({
  storage: storage,
  limits: {
    fileSize: 5 * 1024 * 1024,
    files: 5
  },
  fileFilter: fileFilter
})

app.post('/upload', upload.single('file'), (req, res) => {
  if (!req.file) {
    return res.status(400).json({ error: 'No file uploaded' })
  }
  res.json({
    message: 'File uploaded and validated successfully',
    file: req.file
  })
})

app.use((error, req, res, next) => {
  if (error instanceof multer.MulterError) {
    if (error.code === 'LIMIT_FILE_SIZE') {
      return res.status(400).json({ error: 'File too large. Max size is 5MB' })
    }
    if (error.code === 'LIMIT_FILE_COUNT') {
      return res.status(400).json({ error: 'Too many files' })
    }
  }
  res.status(400).json({ error: error.message })
})

The fileFilter function validates both MIME type and file extension to prevent spoofing. The limits object restricts file size and count. Multer errors are caught in error middleware to provide user-friendly messages. Validating both MIME type and extension prevents users from bypassing validation by renaming files.

Best Practice Note

This is the same file validation we use in CoreUI backend systems for secure uploads. Always validate on the server side - never trust client-side validation. For enhanced security, consider using a library like file-type to verify actual file contents rather than just trusting the MIME type and extension.


Speed up your responsive apps and websites with fully-featured, ready-to-use open-source admin panel templates—free to use and built for efficiency.


About the Author