import express from 'express'; import cors from 'cors'; import { fileURLToPath } from 'url'; import { dirname, join } from 'path'; import { readdir } from 'fs/promises'; import archiver from 'archiver'; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); const app = express(); const PORT = process.env.PORT || 3001; // Middleware app.use(cors()); app.use(express.json()); // Servir archivos estáticos (HTML, CSS, JS) app.use(express.static(join(__dirname, 'public'))); // Servir fotos app.use('/photos', express.static(join(__dirname, 'photos'))); // API para listar fotos app.get('/api/photos', async (req, res) => { try { const photosDir = join(__dirname, 'photos'); const files = await readdir(photosDir, { withFileTypes: true }); const photos = files .filter(file => { if (!file.isFile()) return false; const ext = file.name.toLowerCase().split('.').pop(); return ['jpg', 'jpeg', 'png', 'gif', 'webp'].includes(ext); }) .map(file => ({ name: file.name, url: `/photos/${file.name}` })); res.json(photos); } catch (error) { console.error('Error al listar fotos:', error); res.status(500).json({ error: 'Error al listar fotos' }); } }); // API para descargar todas las fotos como ZIP app.get('/api/photos/zip', async (req, res) => { try { const photosDir = join(__dirname, 'photos'); const files = await readdir(photosDir, { withFileTypes: true }); const photoFiles = files.filter(file => { if (!file.isFile()) return false; const ext = file.name.toLowerCase().split('.').pop(); return ['jpg', 'jpeg', 'png', 'gif', 'webp'].includes(ext); }); if (photoFiles.length === 0) { return res.status(404).json({ error: 'No hay fotos para descargar' }); } // Configurar headers para la descarga res.setHeader('Content-Type', 'application/zip'); res.setHeader('Content-Disposition', 'attachment; filename=fotos.zip'); // Crear archivo ZIP const archive = archiver('zip', { zlib: { level: 9 } // Nivel de compresión }); // Manejar errores del archiver archive.on('error', (err) => { console.error('Error al crear ZIP:', err); res.status(500).json({ error: 'Error al crear ZIP' }); }); // Pipe del archivo al response archive.pipe(res); // Agregar archivos al ZIP for (const file of photoFiles) { archive.file(join(photosDir, file.name), { name: file.name }); } // Finalizar el archivo await archive.finalize(); } catch (error) { console.error('Error al generar ZIP:', error); res.status(500).json({ error: 'Error al generar ZIP' }); } }); app.listen(PORT, () => { console.log(`🚀 Servidor de fotos corriendo en http://localhost:${PORT}`); console.log(`📸 API de fotos disponible en http://localhost:${PORT}/api/photos`); });