Files
cms.uldp.edu.vn/middleware/upload.js
2026-04-11 11:09:16 +07:00

171 lines
5.2 KiB
JavaScript

const multer = require('multer');
const path = require('path');
const fs = require('fs');
const sharp = require('sharp');
// Cấu hình storage cho multer
const storage = multer.diskStorage({
destination: function (req, file, cb) {
try {
// Lấy loại ảnh từ request fields
const imageType = req.query.imageType || 'general';
// Tạo đường dẫn đến thư mục lưu trữ
const uploadPath = path.join(__dirname, '../public/uploads', imageType);
console.log('Creating upload directory:', uploadPath);
// Kiểm tra và tạo thư mục nếu chưa tồn tại
if (!fs.existsSync(uploadPath)) {
fs.mkdirSync(uploadPath, { recursive: true });
console.log('Directory created successfully');
}
cb(null, uploadPath);
} catch (error) {
console.error('Error creating directory:', error);
cb(error);
}
},
filename: function (req, file, cb) {
try {
const imageType = req.query.imageType || 'general';
const uploadPath = path.join(__dirname, '../public/uploads', imageType);
// Lấy tên file gốc (sanitize để tránh ký tự đặc biệt)
const originalName = file.originalname.replace(/[^a-zA-Z0-9.-]/g, '_');
const resizePreset = req.query.resizePreset || '';
if (resizePreset) {
const parsedOriginalName = path.parse(originalName);
const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
req.uploadFinalFileName = originalName;
return cb(null, `${parsedOriginalName.name}.__upload__${uniqueSuffix}${parsedOriginalName.ext}`);
}
const fullPath = path.join(uploadPath, originalName);
// Kiểm tra nếu file đã tồn tại
if (fs.existsSync(fullPath)) {
console.log('File already exists, reusing:', originalName);
// Đánh dấu là file đã tồn tại
req.fileAlreadyExists = true;
req.existingFileName = originalName;
cb(null, originalName);
} else {
// File chưa tồn tại, tạo tên mới
console.log('Creating new file:', originalName);
cb(null, originalName);
}
} catch (error) {
console.error('Error in filename function:', error);
// Fallback: tạo tên unique nếu có lỗi
const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
const ext = path.extname(file.originalname);
cb(null, file.fieldname + '-' + uniqueSuffix + ext);
}
}
});
// Lọc file chỉ cho phép ảnh
const fileFilter = (req, file, cb) => {
const allowedTypes = /jpeg|jpg|png|gif|webp|svg/;
const extname = allowedTypes.test(path.extname(file.originalname).toLowerCase());
const mimetype = allowedTypes.test(file.mimetype);
if (extname && mimetype) {
return cb(null, true);
} else {
cb(new Error('Only image files are allowed!'));
}
};
// Cấu hình upload
const upload = multer({
storage: storage,
limits: { fileSize: 50 * 1024 * 1024 }, // Giới hạn 50MB
fileFilter: fileFilter
});
// Cấu hình storage cho video
const videoStorage = multer.diskStorage({
destination: function (req, file, cb) {
// Tạo đường dẫn đến thư mục lưu trữ video
const uploadPath = path.join(__dirname, '../public/uploads/videos');
// Kiểm tra và tạo thư mục nếu chưa tồn tại
if (!fs.existsSync(uploadPath)) {
fs.mkdirSync(uploadPath, { recursive: true });
}
cb(null, uploadPath);
},
filename: function (req, file, cb) {
// Tạo tên file duy nhất bằng cách thêm timestamp
const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
const ext = path.extname(file.originalname);
cb(null, 'video-' + uniqueSuffix + ext);
}
});
// Lọc file chỉ cho phép video
const videoFileFilter = (req, file, cb) => {
const allowedTypes = /mp4|webm/;
const mimetype = allowedTypes.test(file.mimetype);
if (mimetype) {
return cb(null, true);
} else {
cb(new Error('Only mp4 and webm video files are allowed!'));
}
};
// Cấu hình upload video
const uploadVideo = multer({
storage: videoStorage,
limits: { fileSize: 300 * 1024 * 1024 }, // Giới hạn 300MB cho video
fileFilter: videoFileFilter
});
// Middleware để convert ảnh sau khi multer lưu xong
async function convertToWebp(req, res, next) {
if (!req.file) return next();
console.log('🔄 Converting image to webp format...');
console.log('Original file:', req.file.path);
try {
const filePath = req.file.path;
const webpPath = filePath.replace(path.extname(filePath), '.webp');
console.log('Converting to:', webpPath);
await sharp(filePath)
.webp({ quality: 80 })
.toFile(webpPath);
// Xóa file gốc sau khi convert thành công
if (fs.existsSync(filePath)) {
fs.unlinkSync(filePath);
}
// Cập nhật thông tin file
req.file.filename = path.basename(webpPath);
req.file.path = webpPath;
console.log('Image converted successfully');
next();
} catch (err) {
console.error('Error converting image:', err);
console.error('Error details:', err.message);
// Nếu convert thất bại, vẫn tiếp tục với file gốc
next();
}
}
module.exports = {
upload,
uploadVideo,
convertToWebp
};