import multer from "multer"; import crypto from "crypto"; import path from "path"; import fs from "fs"; import response from "../../response.js"; const memoryStorage = multer.memoryStorage(); const fileFilter = (req, file, cb) => { const ext = path.extname(file.originalname).toLowerCase(); if (file.fieldname.startsWith("AUDIO")) { if (ext === ".mp3") { cb(null, true); } else { cb( new Error("Invalid file type, only .mp3 files are allowed for audio!"), false ); } } else if (file.fieldname.startsWith("IMAGE")) { if (ext === ".jpg" || ext === ".jpeg" || ext === ".png") { cb(null, true); } else { cb( new Error( "Invalid file type, only .jpg, .jpeg, and .png files are allowed for image!" ), false ); } } else { cb(new Error("Invalid file type!"), false); } }; const upload = multer({ storage: memoryStorage, fileFilter, limits: { fileSize: 100 * 1024 * 1024, }, }).any(); const handleUploadFile = (req, res, next) => { upload(req, res, (err) => { if (err) { return response(400, null, err.message, res); } const files = req.files || []; req.filesToSave = {}; let validFiles = true; let errorMessages = []; files.forEach((file) => { if (file.fieldname.startsWith("AUDIO")) { if (file.size > 10 * 1024 * 1024) { validFiles = false; errorMessages.push(`Audio file exceeds the size limit of 10MB`); } else { req.filesToSave[file.fieldname] = file; } } else if (file.fieldname.startsWith("IMAGE")) { if (file.size > 5 * 1024 * 1024) { validFiles = false; errorMessages.push(`Image file exceeds the size limit of 5MB`); } else { req.filesToSave[file.fieldname] = file; } } }); if (validFiles) { next(); } else { clearFileBuffers(req.filesToSave); return response(400, null, errorMessages.join("; "), res); } }); }; export const clearFileBuffers = (files) => { for (const file of Object.values(files)) { if (file && file.buffer) { file.buffer = null; } } }; export const generateHash = ( levelId, sectionId, topicId, filename, bufferLength ) => { return crypto .createHash("md5") .update(levelId + sectionId + topicId + filename + bufferLength) .digest("hex"); }; export const saveFileToDisk = (file, type, topicId, sectionId, levelId) => { const ext = path.extname(file.originalname); const hash = generateHash( levelId, sectionId, topicId, file.originalname, file.buffer.length ); const filename = `${type}-${levelId}-${hash}${ext}`; let folderPath; switch (type) { case "AUDIO": folderPath = path.join(process.cwd(), "media/uploads/level/audio"); break; case "IMAGE": folderPath = path.join(process.cwd(), "media/uploads/level/image"); break; default: folderPath = path.join(process.cwd(), "media/uploads/level"); } if (!fs.existsSync(folderPath)) { fs.mkdirSync(folderPath, { recursive: true }); } const filepath = path.join(folderPath, filename); fs.writeFileSync(filepath, file.buffer); return filename; }; export default handleUploadFile;