From 97a12d700a53f1b986538108b37585f35e933596 Mon Sep 17 00:00:00 2001 From: Rafael Lopes Date: Wed, 22 Jul 2026 16:28:36 -0300 Subject: [PATCH] =?UTF-8?q?FEAT:=20Adiciona=20valida=C3=A7=C3=B5es=20de=20?= =?UTF-8?q?tipo=20e=20tamanho=20no=20envio=20de=20m=C3=ADdia?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - fileFilter no Multer rejeita tipos não suportados antes de bufferizar - Limite por tipo: imagem 5 MB, áudio/vídeo 16 MB, documento 100 MB - Erro retornado ao frontend em caso de violação --- src/modules/whatsapp/whatsapp.controller.ts | 39 ++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/src/modules/whatsapp/whatsapp.controller.ts b/src/modules/whatsapp/whatsapp.controller.ts index 8b4c1f7..880ab7e 100644 --- a/src/modules/whatsapp/whatsapp.controller.ts +++ b/src/modules/whatsapp/whatsapp.controller.ts @@ -1,5 +1,23 @@ import { Controller, Get, Post, Body, Delete, Param, ForbiddenException, Query, UseInterceptors, UploadedFile, BadRequestException } from '@nestjs/common'; import { FileInterceptor } from '@nestjs/platform-express'; + +const ALLOWED_MEDIA_TYPES = new Set([ + 'image/jpeg', 'image/png', 'image/webp', 'image/gif', + 'audio/mpeg', 'audio/mp4', 'audio/ogg', 'audio/wav', 'audio/aac', 'audio/amr', + 'video/mp4', 'video/3gpp', + 'application/pdf', + 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + 'application/msword', + 'application/vnd.ms-excel', +]); + +const MAX_SIZE_MB: Record = { + image: 5, + audio: 16, + video: 16, + document: 100, +}; import { ApiBody, ApiOperation, ApiParam, ApiResponse, ApiTags } from '@nestjs/swagger'; import { WhatsappService } from './whatsapp.service'; import { AttendanceAssignmentService } from '../attendance/attendance-assignment.service'; @@ -68,7 +86,16 @@ export class WhatsappController { @ApiOperation({ summary: 'Envia mídia no WhatsApp' }) @ApiResponse({ status: 201, description: 'Mídia enviada.' }) @Post('send-media') - @UseInterceptors(FileInterceptor('file', { limits: { fileSize: 100 * 1024 * 1024 } })) + @UseInterceptors(FileInterceptor('file', { + limits: { fileSize: 100 * 1024 * 1024 }, + fileFilter: (_req, file, cb) => { + if (ALLOWED_MEDIA_TYPES.has(file.mimetype)) { + cb(null, true); + } else { + cb(new BadRequestException(`Tipo de arquivo não suportado: ${file.mimetype}`), false); + } + }, + })) async sendMediaMessage( @UploadedFile() file: Express.Multer.File, @Body('to') to: string, @@ -77,6 +104,16 @@ export class WhatsappController { ) { if (!file) throw new BadRequestException('Arquivo não enviado.'); if (!to) throw new BadRequestException('Destinatário (to) obrigatório.'); + + const mediaType = file.mimetype.startsWith('image/') ? 'image' + : file.mimetype.startsWith('audio/') ? 'audio' + : file.mimetype.startsWith('video/') ? 'video' + : 'document'; + const limitMB = MAX_SIZE_MB[mediaType]; + if (file.size > limitMB * 1024 * 1024) { + throw new BadRequestException(`Arquivo muito grande. Limite para ${mediaType}: ${limitMB} MB.`); + } + return this.whatsappService.sendMediaMessage(to, file.buffer, file.mimetype, senderName, caption); }