omnichannel-backend/src/modules/whatsapp/media/adapters/local-disk.adapter.ts
Rafael Lopes 4ab3af503b
Some checks failed
Deploy Dev / deploy (push) Has been cancelled
FEAT: Adiciona camada de storage de mídia (LocalDiskAdapter)
- MediaStorageService com interface upload/getUrl/delete
- LocalDiskAdapter salva em /uploads/media/ com UUID + extensão por mimetype
- Cria o diretório automaticamente no boot
- BASE_URL adicionado ao .env.example
- MediaStorageService e LocalDiskAdapter registrados no WhatsappModule
2026-07-21 09:47:44 -03:00

49 lines
1.5 KiB
TypeScript

import { Injectable, Logger } from '@nestjs/common';
import * as fs from 'fs';
import * as path from 'path';
import { randomUUID } from 'crypto';
const UPLOAD_DIR = path.resolve(process.cwd(), 'uploads', 'media');
const MIME_TO_EXT: Record<string, string> = {
'image/jpeg': '.jpg',
'image/png': '.png',
'image/webp': '.webp',
'audio/ogg': '.ogg',
'audio/mpeg': '.mp3',
'audio/mp4': '.m4a',
'audio/amr': '.amr',
'video/mp4': '.mp4',
'video/3gpp': '.3gp',
'application/pdf': '.pdf',
'application/vnd.openxmlformats-officedocument.wordprocessingml.document': '.docx',
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': '.xlsx',
'application/vnd.openxmlformats-officedocument.presentationml.presentation': '.pptx',
};
@Injectable()
export class LocalDiskAdapter {
private readonly logger = new Logger(LocalDiskAdapter.name);
constructor() {
fs.mkdirSync(UPLOAD_DIR, { recursive: true });
}
async upload(buffer: Buffer, mimeType: string): Promise<string> {
const ext = MIME_TO_EXT[mimeType] ?? '.bin';
const filename = `${randomUUID()}${ext}`;
const filepath = path.join(UPLOAD_DIR, filename);
fs.writeFileSync(filepath, buffer);
this.logger.log(`Mídia salva: ${filepath}`);
return `/uploads/media/${filename}`;
}
delete(relativePath: string): void {
try {
fs.unlinkSync(path.join(process.cwd(), relativePath));
} catch {
this.logger.warn(`Falha ao deletar mídia: ${relativePath}`);
}
}
}