FileDummy Logo
FileDummy
File Upload & Handling

File Upload Validation: Size, Type & Extension (Frontend + Backend)

Complete guide to file upload validation — checking size, MIME type, and extension on both frontend and backend with Node.js. Download exact-size test files.

October 11, 20268 min read1,420 views
javascriptnodejsvalidationfile-uploadsecurity

Securing file upload endpoints requires rigorous validation. Accepting unvalidated files exposes servers to denial-of-service (disk exhaustion), remote code execution (RCE), and cross-site scripting (XSS). This tutorial demonstrates two-tier validation on both frontend and backend.

The Rule of Dual Validation

  • Client-Side: Provides immediate feedback and saves client bandwidth. Never trust client validation for security.
  • Server-Side: The true barrier. Verifies file size, actual content magic bytes, and sanitizes filenames before saving to disk or object storage.
Verified Test Asset.pdf

Download our 100MB PDF sample file to test your client and server maximum upload size constraints.

Download 100MB PDF Sample →

Client-Side Validation (React / Vanilla JS)

TypeScript
const ALLOWED_MIME_TYPES = ['application/pdf', 'image/jpeg', 'image/png'];
const MAX_FILE_SIZE = 25 * 1024 * 1024; // 25MB

export function validateFileBeforeUpload(file: File): { valid: boolean; error?: string } {
  if (file.size === 0) {
    return { valid: false, error: 'File is empty (0 bytes).' };
  }

  if (file.size > MAX_FILE_SIZE) {
    return {
      valid: false,
      error: `File size (${(file.size / (1024 * 1024)).toFixed(1)}MB) exceeds 25MB limit.`,
    };
  }

  if (!ALLOWED_MIME_TYPES.includes(file.type)) {
    return {
      valid: false,
      error: 'Invalid file format. Only PDF, JPG, and PNG are permitted.',
    };
  }

  return { valid: true };
}

Server-Side Validation in Express / Node.js

Always enforce limits in your middleware layer so oversized requests are rejected before consuming server RAM:

TypeScript
import express from 'express';
import multer from 'multer';

const upload = multer({
  limits: {
    fileSize: 25 * 1024 * 1024, // 25 MB max
    files: 1,
  },
  fileFilter: (req, file, cb) => {
    const allowedTypes = ['application/pdf', 'image/jpeg', 'image/png'];
    if (!allowedTypes.includes(file.mimetype)) {
      return cb(new Error('LIMIT_UNEXPECTED_FILETYPE'));
    }
    cb(null, true);
  },
});

const app = express();

app.post('/api/upload', upload.single('document'), (req, res) => {
  if (!req.file) {
    return res.status(400).json({ error: 'No file uploaded' });
  }

  res.status(200).json({
    message: 'File successfully validated and received',
    filename: req.file.originalname,
    size: req.file.size,
  });
});

Security Checklist

  1. Sanitize filenames: Strip path traversal characters (.., /, \) and unicode control bytes.
  2. Do not execute in place: Store uploads outside the web server root or in object storage (S3/R2).
  3. Randomize storage keys: Save as UUIDs (e.g. uuidv4() + '.pdf') instead of the user-supplied filename.
NDL

Nguyen Dai Long

Author

Backend Lead • Distributed Systems & Cloud Edge Architecture Specialist

4+ years designing high-throughput file ingestion pipelines, database architectures, and distributed edge storage on Cloudflare R2 & AWS S3. Founder of FileDummy and the NDL Ecosystem.

Was this article helpful?

Click Like to support the author and help other developers discover this guide.

Engineering Discussion & Feedback (0)

Share benchmark results, report edge cases, or ask technical questions.

0/3000

No comments yet. Be the first developer to start the discussion!

Frequently Asked Questions

Is client-side file validation enough?▾

No. Client-side validation improves UX but must never replace server-side validation. Users can bypass browser checks with developer tools or direct API calls. Always validate on the server before processing.

How do I check file type without relying on the extension?▾

Read the file's magic bytes (the first 4–8 bytes). PDF files start with %PDF, ZIP/DOCX with PK\x03\x04, JPEG with \xFF\xD8\xFF. Use the file-type npm package in Node.js for easy magic byte detection.

What is a safe maximum upload size for web apps?▾

Common limits: email (10–25MB), social media avatars (5–10MB), document uploads in SaaS (50–100MB). For large files, use multipart or resumable uploads and set both client-side and server-side (nginx body limit, Express bodyParser) constraints.

Related Articles