FileDummy Logo
FileDummy
Tải Lên & Xử Lý Tệp Tin

Xác Thực Tệp Tải Lên: Kích Thước, Định Dạng & Đuôi File (Frontend + Backend)

Hướng dẫn toàn diện về kiểm tra kích thước, MIME type và phần mở rộng trên cả Frontend và Backend Node.js. Tải file mẫu kích thước chuẩn xác.

11 tháng 10, 20268 phút đọc1,420 lượt xem
javascriptnodejsvalidationfile-uploadsecurity

Bảo mật endpoint tải lên tệp đòi hỏi xác thực nghiêm ngặt. Chấp nhận tệp không được xác thực khiến máy chủ bị lộ trước tấn công từ chối dịch vụ (hết đĩa), thực thi code từ xa (RCE) và cross-site scripting (XSS). Hướng dẫn này trình bày xác thực hai tầng cả phía frontend và backend.

Quy Tắc Xác Thực Hai Tầng

  • Phía Client: Cung cấp phản hồi tức thì và tiết kiệm băng thông client. Không bao giờ tin tưởng xác thực client cho mục đích bảo mật.
  • Phía Server: Rào cản thực sự. Xác minh kích thước tệp, magic byte nội dung thực tế và làm sạch tên tệp trước khi lưu vào đĩa hoặc object storage.
Thử Nghiệm Thực Tế.pdf

Tải file PDF mẫu 100MB để kiểm thử ràng buộc kích thước tải lên tối đa phía client và server.

Tải File Mẫu 100MB PDF →

Xác Thực Phía Client (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: 'Tệp rỗng (0 byte).' };
  }

  if (file.size > MAX_FILE_SIZE) {
    return {
      valid: false,
      error: `Kích thước tệp (${(file.size / (1024 * 1024)).toFixed(1)}MB) vượt quá giới hạn 25MB.`,
    };
  }

  if (!ALLOWED_MIME_TYPES.includes(file.type)) {
    return {
      valid: false,
      error: 'Định dạng tệp không hợp lệ. Chỉ cho phép PDF, JPG và PNG.',
    };
  }

  return { valid: true };
}

Xác Thực Phía Server Trong Express / Node.js

Luôn áp dụng giới hạn trong middleware để các request quá kích thước bị từ chối trước khi tiêu thụ RAM máy chủ:

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

const upload = multer({
  limits: {
    fileSize: 25 * 1024 * 1024, // tối đa 25 MB
    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: 'Không có tệp nào được tải lên' });
  }

  res.status(200).json({
    message: 'Tệp đã được xác thực và nhận thành công',
    filename: req.file.originalname,
    size: req.file.size,
  });
});

Danh Sách Kiểm Tra Bảo Mật

  1. Làm sạch tên tệp: Loại bỏ các ký tự path traversal (.., /, \) và byte kiểm soát unicode.
  2. Không thực thi tại chỗ: Lưu tệp tải lên ngoài web server root hoặc trong object storage (S3/R2).
  3. Ngẫu nhiên hóa khóa lưu trữ: Lưu dưới dạng UUID (ví dụ: uuidv4() + '.pdf') thay vì tên tệp do người dùng cung cấp.
NDL

Nguyễn Đại Long

Tác Giả

Backend Lead • Chuyên gia Kiến trúc Hệ thống Phân tán & Lưu trữ Đám mây

Hơn 4 năm kinh nghiệm thiết kế các hệ thống xử lý tệp tải lên thông lượng lớn, tối ưu hóa cơ sở dữ liệu và hạ tầng phân tán Cloudflare R2 / AWS S3. Người sáng lập FileDummy và Mạng lưới Hệ sinh thái NDL.

Bài viết này có hữu ích không?

Bấm Thích để ủng hộ tác giả và giúp bài viết lan tỏa tới cộng đồng lập trình viên.

Thảo Luận Kỹ Thuật & Đóng Góp Ý Kiến (0)

Chia sẻ kết quả benchmark, phản hồi các trường hợp biên hoặc đặt câu hỏi chuyên môn.

0/3000

Chưa có bình luận nào. Hãy là lập trình viên đầu tiên bắt đầu cuộc thảo luận!

Câu Hỏi Thường Gặp (FAQ)

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.

Bài Viết Liên Quan