Node.js8 min read

File Uploads with Multer in Express

Handle file uploads in Node.js with Multer. Upload images, documents, and manage file storage.

Sarah Chen
December 19, 2025
0.0k0

File Uploads with Multer in Express

Multer handles multipart/form-data - the format for file uploads.

Setup

npm install multer

Basic Configuration

const multer = require('multer');

// Simple memory storage
const upload = multer({ dest: 'uploads/' });

// Or disk storage with custom naming
const storage = multer.diskStorage({
  destination: (req, file, cb) => {
    cb(null, 'uploads/');
  },
  filename: (req, file, cb) => {
    const uniqueName = Date.now() + '-' + file.originalname;
    cb(null, uniqueName);
  }
});

const upload = multer({ storage });

Single File Upload

app.post('/upload', upload.single('avatar'), (req, res) => {
  console.log(req.file);
  // {
  //   fieldname: 'avatar',
  //   originalname: 'photo.jpg',
  //   filename: '1234567890-photo.jpg',
  //   path: 'uploads/1234567890-photo.jpg',
  //   size: 12345
  // }
  res.json({ file: req.file });
});

Multiple Files

// Multiple files, same field
app.post('/photos', upload.array('photos', 5), (req, res) => {
  console.log(req.files);  // Array of files
  res.json({ files: req.files });
});

// Multiple fields
const cpUpload = upload.fields([
  { name: 'avatar', maxCount: 1 },
  { name: 'gallery', maxCount: 8 }
]);

app.post('/profile', cpUpload, (req, res) => {
  console.log(req.files.avatar);   // Single file
  console.log(req.files.gallery);  // Array of files
});

File Filtering

const imageFilter = (req, file, cb) => {
  const allowedTypes = ['image/jpeg', 'image/png', 'image/gif'];
  
  if (allowedTypes.includes(file.mimetype)) {
    cb(null, true);
  } else {
    cb(new Error('Only images allowed'), false);
  }
};

const upload = multer({
  storage,
  fileFilter: imageFilter,
  limits: {
    fileSize: 5 * 1024 * 1024  // 5MB
  }
});

Error Handling

app.post('/upload', (req, res) => {
  upload.single('file')(req, res, (err) => {
    if (err instanceof multer.MulterError) {
      if (err.code === 'LIMIT_FILE_SIZE') {
        return res.status(400).json({ error: 'File too large' });
      }
      return res.status(400).json({ error: err.message });
    }
    if (err) {
      return res.status(400).json({ error: err.message });
    }
    res.json({ file: req.file });
  });
});

Memory Storage (for cloud upload)

const upload = multer({ storage: multer.memoryStorage() });

app.post('/upload', upload.single('file'), async (req, res) => {
  // req.file.buffer contains file data
  // Upload to S3, Cloudinary, etc.
  
  const buffer = req.file.buffer;
  // await uploadToCloud(buffer);
  
  res.json({ message: 'Uploaded' });
});

Complete Example

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

const app = express();

const storage = multer.diskStorage({
  destination: 'uploads/',
  filename: (req, file, cb) => {
    const ext = path.extname(file.originalname);
    cb(null, `${Date.now()}${ext}`);
  }
});

const upload = multer({
  storage,
  limits: { fileSize: 5 * 1024 * 1024 },
  fileFilter: (req, file, cb) => {
    const allowed = /jpeg|jpg|png|gif/;
    const ext = allowed.test(path.extname(file.originalname).toLowerCase());
    const mime = allowed.test(file.mimetype);
    
    if (ext && mime) cb(null, true);
    else cb(new Error('Images only!'));
  }
});

// Serve uploaded files
app.use('/uploads', express.static('uploads'));

app.post('/api/upload', upload.single('image'), (req, res) => {
  if (!req.file) {
    return res.status(400).json({ error: 'No file uploaded' });
  }
  
  res.json({
    url: `/uploads/${req.file.filename}`,
    size: req.file.size
  });
});

app.listen(3000);

Key Takeaway

Multer handles file uploads in Express. Use single() for one file, array() for multiple. Filter by type/size for security. Use memory storage for cloud uploads, disk storage for local files.

#Node.js#Express#File Upload#Multer#Intermediate