const multer = require('multer'); const path = require('path'); const fs = require('fs'); const { response } = require('../helpers/utils/wrapper') const uploadDir = process.env.NODE_ENV === 'production' ? '/tmp/uploads' : path.join(__dirname, '../uploads'); if (!fs.existsSync(uploadDir)) { fs.mkdirSync(uploadDir, { recursive: true }); } const storage = multer.diskStorage({ destination: (_req, _file, cb) => cb(null, uploadDir), filename: (_req, file, cb) => { const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9); const safeExt = path.extname(file.originalname).replace(/[^a-zA-Z0-9.]/g, '').toLowerCase(); cb(null, `${uniqueSuffix}${safeExt}`); }, }); const fileFilter = (req, file, cb) => { const allowedMimeTypes = [ 'image/jpeg', 'image/jpg', 'image/png', 'application/pdf' ]; if (allowedMimeTypes.includes(file.mimetype)) { cb(null, true); } else { const errMsg = 'Can only upload images (jpeg, jpg, png) or PDF files'; req.fileValidationError = errMsg; cb(new Error(errMsg), false); } }; const upload = multer({ storage: storage, fileFilter: fileFilter, limits: { fileSize: 5 * 1024 * 1024, // 5MB Makss files: 5, }, }); // middleware untuk ngechek ukuran file const checkFileSizes = (req, res, next) => { const maxSize = 5 * 1024 * 1024; // 5MB const errors = {}; const filesToDelete = []; const allFiles = []; // ini untuk 1 file if (req.file) allFiles.push(req.file); // ini untuk multiple files if (req.files) { if (Array.isArray(req.files)) { allFiles.push(...req.files); } else { Object.values(req.files).flat().forEach(file => allFiles.push(file)); } } allFiles.forEach(file => { if (file.size > maxSize) { errors[file.fieldname] = `Ukuran file ${file.fieldname} terlalu besar. Maksimal 5MB`; } filesToDelete.push(file.path); }); // ini untuk jika ada error maka file yang terupload dihapus if (Object.keys(errors).length > 0) { filesToDelete.forEach(filePath => { if (fs.existsSync(filePath)) fs.unlinkSync(filePath); }); return res.status(413).json({ status: false, data: null, message: errors, code: 413, }); } next(); }; // middleware untuk error multer const multerErrorHandler = (err, req, res, next) => { if (err instanceof multer.MulterError) { if (err.code === 'LIMIT_FILE_SIZE') { return res.status(413).json({ status: false, data: null, message: 'Ukuran file terlalu besar. Maksimal 5MB', code: 413, }); } if (err.code === 'LIMIT_UNEXPECTED_FILE') { return res.status(400).json({ status: false, data: null, message: { [err.field]: `Field '${err.field}' tidak boleh memiliki lebih dari 1 file.`, }, code: 400, }); } return res.status(400).json({ status: false, data: null, message: err.message, code: 400, }); } if (err) { return res.status(400).json({ status: false, data: null, message: err.message || 'Error saat upload file', code: 400, }); } next(); }; module.exports = upload; module.exports.multerErrorHandler = multerErrorHandler; module.exports.checkFileSizes = checkFileSizes;