const path = require('path'); const fs = require('fs'); const crypto = require('crypto'); const UPLOADS_DIR = path.join(__dirname, '..', 'public', 'uploads', 'herramientas'); // Asegurar existencia del directorio de uploads if (!fs.existsSync(UPLOADS_DIR)) { fs.mkdirSync(UPLOADS_DIR, { recursive: true }); } const ALLOWED_MIME_TYPES = [ 'image/jpeg', 'image/png', 'image/webp', 'image/gif' ]; const ALLOWED_EXTENSIONS = ['.jpg', '.jpeg', '.png', '.webp', '.gif']; /** * Guarda una imagen subida mediante express-fileupload en public/uploads/herramientas/ * @param {Object} fileObj - Objeto de archivo de req.files * @param {string} prefix - Prefijo descriptivo del archivo (ej: 'herramienta', 'kit', 'entrega', 'devolucion') * @returns {Promise} - Ruta pública (/uploads/herramientas/...) o null si no se proporcionó archivo */ async function guardarFoto(fileObj, prefix = 'herramienta') { if (!fileObj || !fileObj.name || !fileObj.data) { return null; } const ext = path.extname(fileObj.name).toLowerCase(); if (!ALLOWED_EXTENSIONS.includes(ext) || !ALLOWED_MIME_TYPES.includes(fileObj.mimetype)) { throw new Error('Formato de imagen no soportado. Formatos válidos: JPG, PNG, WEBP, GIF.'); } // Límite de 8 MB if (fileObj.size > 8 * 1024 * 1024) { throw new Error('La imagen excede el límite máximo de 8MB.'); } const randomSuffix = crypto.randomBytes(6).toString('hex'); const safeFilename = `${prefix}_${Date.now()}_${randomSuffix}${ext}`; const targetPath = path.join(UPLOADS_DIR, safeFilename); await new Promise((resolve, reject) => { fileObj.mv(targetPath, (err) => { if (err) return reject(err); resolve(); }); }); return `/uploads/herramientas/${safeFilename}`; } module.exports = { guardarFoto, UPLOADS_DIR };