Upload File (Multer)
Trong Node.js, để xử lý tính năng upload file (như hình ảnh, tài liệu, video) từ phía Client gửi lên, thư viện chuẩn mực và phổ biến nhất được sử dụng là Multer. Multer là một middleware của Express.js, chuyên xử lý dữ liệu định dạng multipart/form-data (định dạng bắt buộc khi gửi file qua […]
Trong Node.js, để xử lý tính năng upload file (như hình ảnh, tài liệu, video) từ phía Client gửi lên, thư viện chuẩn mực và phổ biến nhất được sử dụng là Multer.
Multer là một middleware của Express.js, chuyên xử lý dữ liệu định dạng multipart/form-data (định dạng bắt buộc khi gửi file qua form) [shopping].
Cài đặt thư viện
Chạy lệnh sau tại thư mục dự án của bạn để cài đặt:
npm install express multer
Cấu hình Multer (Tầng Middleware)
Lập trình viên thực tế sẽ không lưu trực tiếp file vào bộ nhớ tạm mà sẽ cấu hình DiskStorage để chỉ định rõ ràng: File lưu ở thư mục nào và tên file được đổi như thế nào nhằm tránh trùng lặp.
// file: middlewares/upload.middleware.js
const multer = require('multer');
const path = require('path');
// 1. Cấu hình nơi lưu trữ và cách đặt tên file
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, 'uploads/'); // Thư mục file sẽ được lưu vào (Hãy tạo sẵn thư mục này)
},
filename: (req, file, cb) => {
// Tạo tên file duy nhất: Thời-gian-hiện-tại + Số-ngẫu-nhiên + Đuôi-file-gốc
const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
const fileExtension = path.extname(file.originalname); // Lấy đuôi file (.jpg, .png...)
cb(null, file.fieldname + '-' + uniqueSuffix + fileExtension);
}
});
// 2. Bộ lọc định dạng file (Chỉ cho phép upload ảnh)
const fileFilter = (req, file, cb) => {
const allowedTypes = /jpeg|jpg|png|gif/;
const extname = allowedTypes.test(path.extname(file.originalname).toLowerCase());
const mimetype = allowedTypes.test(file.mimetype);
if (extname && mimetype) {
return cb(null, true); // Chấp nhận file
} else {
cb(new Error('Chỉ chấp nhận file định dạng hình ảnh (jpg, jpeg, png, gif)!'), false);
}
};
// 3. Khởi tạo cấu hình Multer hoàn chỉnh
const upload = multer({
storage: storage,
fileFilter: fileFilter,
limits: { fileSize: 2 * 1024 * 1024 } // Giới hạn dung lượng tối đa: 2MB
});
module.exports = upload;
Triển khai API nhận File (Tầng Controller & Route)
Khi Multer xử lý xong, thông tin của file sẽ được nạp trực tiếp vào đối tượng req.file (nếu upload 1 file) hoặc req.files (nếu upload nhiều file).
A: Upload duy nhất 1 file (Ví dụ: Ảnh đại diện Avatar)
Sử dụng hàm .single(‘tên_trường_gửi_lên’).
const express = require('express');
const router = express.Router();
const upload = require('./middlewares/upload.middleware');
router.post('/upload-avatar', upload.single('avatar'), (req, res) => {
try {
if (!req.file) {
return res.status(400).json({ message: 'Vui lòng chọn file để upload!' });
}
// Thông tin file được lưu thành công nằm trong req.file
res.status(200).json({
message: 'Upload ảnh đại diện thành công!',
fileInfo: {
fileName: req.file.filename,
path: req.file.path,
size: `${(req.file.size / 1024).toFixed(2)} KB`
}
});
} catch (error) {
res.status(500).json({ error: error.message });
}
});
B: Upload nhiều file cùng lúc (Ví dụ: Ảnh Album sản phẩm)
Sử dụng hàm .array(‘tên_trường_gửi_lên’, số_lượng_tối_đa).
router.post('/upload-images', upload.array('photos', 5), (req, res) => {
try {
if (!req.files || req.files.length === 0) {
return res.status(400).json({ message: 'Vui lòng chọn ít nhất 1 file!' });
}
// Thông tin các file nằm trong mảng req.files
const fileUrls = req.files.map(file => file.path);
res.status(200).json({
message: `Đã upload thành công ${req.files.length} hình ảnh!`,
paths: fileUrls
});
} catch (error) {
res.status(500).json({ error: error.message });
}
});
Phục vụ file tĩnh (Static Files) để Client có thể xem được ảnh
Mặc định, khi bạn truy cập vào đường dẫn file dạng http://localhost:3000/uploads/ten-anh.jpg, Express sẽ báo lỗi 404 Not Found vì lý do bảo mật. Để cho phép Client truy cập và xem được ảnh, bạn cần kích hoạt middleware tích hợp sẵn express.static trong file chạy chính (app.js hoặc server.js):
const express = require('express');
const path = require('path');
const app = express();
// Biến thư mục 'uploads' thành thư mục công khai (Static folder)
app.use('/public/uploads', express.static(path.join(__dirname, 'uploads')));
// Giờ đây Client có thể xem ảnh bằng đường dẫn:
// http://localhost:3000/public/uploads/avatar-171829312.png
Xử lý lỗi Multer tập trung (Error Handling)
Nếu Client cố tình gửi file nặng hơn 2MB hoặc gửi sai định dạng, Multer sẽ quẳng ra một lỗi hệ thống làm sập API. Để xử lý mượt mà, hãy đưa nó vào chuỗi Middleware xử lý lỗi tập trung:
// Đặt ở cuối cùng của file app.js, sau tất cả các route
app.use((err, req, res, next) => {
if (err instanceof multer.MulterError) {
// Các lỗi do cấu hình giới hạn của Multer (ví dụ quá dung lượng)
if (err.code === 'LIMIT_FILE_SIZE') {
return res.status(400).json({ message: 'File quá lớn! Dung lượng tối đa cho phép là 2MB.' });
}
return res.status(400).json({ message: err.message });
} else if (err) {
// Lỗi do bộ lọc fileFilter tự định nghĩa của chúng ta
return res.status(400).json({ message: err.message });
}
next();
});
Lưu ý quan trọng khi dùng Postman để test API Upload File
Khi bạn dùng phần mềm Postman để kiểm thử API này:
- Tại tab Body, bạn bắt buộc phải chọn định dạng form-data.
- Tại cột KEY, nhập chính xác tên trường bạn đã cấu hình (ví dụ: avatar hoặc photos).
- Rê chuột vào cuối ô KEY, chọn kiểu dữ liệu từ Text chuyển sang File. Lúc này nút Select Files sẽ xuất hiện ở cột VALUE để bạn chọn ảnh từ máy tính gửi lên.