Subida de Archivos
Aprende a manejar uploads de imágenes con Multer.
Instalación
bash
npm install multernpm install -D @types/multerConfiguración de Multer
typescript
// src/config/upload.tsimport multer, { FileFilterCallback } from 'multer';import path from 'path';import crypto from 'crypto';import { Request } from 'express';import { AppError } from '../errors/AppError'; const uploadFolder = path.resolve(__dirname, '..', '..', 'uploads'); const storage = multer.diskStorage({ destination: (req, file, cb) => { cb(null, uploadFolder); }, filename: (req, file, cb) => { const hash = crypto.randomBytes(16).toString('hex'); const extension = path.extname(file.originalname); const filename = `${hash}${extension}`; cb(null, filename); },}); const fileFilter = ( req: Request, file: Express.Multer.File, cb: FileFilterCallback) => { const allowedMimes = ['image/jpeg', 'image/png', 'image/webp']; if (allowedMimes.includes(file.mimetype)) { cb(null, true); } else { cb(new AppError('Tipo de archivo no permitido', 400)); }}; export const upload = multer({ storage, fileFilter, limits: { fileSize: 5 * 1024 * 1024, // 5MB },});Ruta de Upload
typescript
// src/routes/upload.routes.tsimport { Router } from 'express';import { upload } from '../config/upload';import { authenticate, authorize } from '../middlewares'; const router = Router(); // Subir imagen de productorouter.post('/products/:id/images', authenticate, authorize('ADMIN'), upload.array('images', 5), async (req, res) => { const files = req.files as Express.Multer.File[]; const images = files.map(file => ({ filename: file.filename, url: `/uploads/${file.filename}`, })); // Guardar URLs en el producto await prisma.product.update({ where: { id: req.params.id }, data: { images: { push: images.map(img => img.url), }, }, }); res.json({ images }); });Servir Archivos Estáticos
typescript
// src/app.tsimport express from 'express';import path from 'path'; app.use('/uploads', express.static(path.resolve(__dirname, '..', 'uploads')));Upload a AWS S3
typescript
// src/config/s3.tsimport { S3Client, PutObjectCommand, DeleteObjectCommand } from '@aws-sdk/client-s3';import multer from 'multer';import multerS3 from 'multer-s3'; const s3 = new S3Client({ region: process.env.AWS_REGION, credentials: { accessKeyId: process.env.AWS_ACCESS_KEY_ID!, secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!, },}); export const uploadS3 = multer({ storage: multerS3({ s3, bucket: process.env.AWS_BUCKET_NAME!, contentType: multerS3.AUTO_CONTENT_TYPE, key: (req, file, cb) => { const filename = `${Date.now()}-${file.originalname}`; cb(null, `products/${filename}`); }, }), limits: { fileSize: 5 * 1024 * 1024 },}); // Eliminar de S3export const deleteFromS3 = async (key: string) => { await s3.send(new DeleteObjectCommand({ Bucket: process.env.AWS_BUCKET_NAME!, Key: key, }));};Resumen
- ✅ Upload local con Multer
- ✅ Validación de tipo y tamaño
- ✅ Archivos estáticos
- ✅ Upload a S3 (producción)
Próxima clase: Envío de Emails! 🚀