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 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 };