DEV Community

Leonardo Minora
Leonardo Minora

Posted on • Edited on

NestJS - Validando o envio de arquivos

Informações gerais

  • aula com FIXME para os alunos de programação orientada a serviços, do 4o ano de infoweb, do CNAT-IFRN
  • repositório de código
  • código final branch zip

objetivo

  • validar os arquivos enviados com validadores do nestjs
  • validar os arquivos enviados com validador personalizado

notas de aula

sumário

  1. pegar o código base
  2. acessar pasta do projeto e instalar bibliotecas do projeto
  3. executar a api
  4. incluir módulo nestjs para os novos endpoints
  5. codar 1 endpoint com validação nestjs para envio de imagem png
  6. codar 1 endpoint com validação nestjs para envio de imagem jpeg
  7. codar 1 endpoint com validação personalizada para envio de imagens

1. pegar o código base

pode utilizar o seu próprio código, ou baixar o zip ou fazer o clone do repositório github com o código-fonte do projeto da nota de aula anterior.

lembrando que fazendo o clone do repositório github, precisará executar na pasta do projeto o comando git checkout -b 05-upload-validacao origin/05-upload-validacao.

2. acessar pasta do projeto e instalar bibliotecas do projeto

[upload-api] $ npm install

Enter fullscreen mode Exit fullscreen mode

3. executar a api

[upload-api] $ npm run start:dev

Enter fullscreen mode Exit fullscreen mode

após lançar a api, o terminal deverá parecer como o console abaixo.

[14:44:53] Starting compilation in watch mode...

[14:44:56] Found 0 errors. Watching for file changes.

[Nest] 359207  - 20/09/2024, 14:44:57     LOG [NestFactory] Starting Nest application...
[Nest] 359207  - 20/09/2024, 14:44:57     LOG [InstanceLoader] ConfigHostModule dependencies initialized +22ms
[Nest] 359207  - 20/09/2024, 14:44:57     LOG [InstanceLoader] AppModule dependencies initialized +1ms
[Nest] 359207  - 20/09/2024, 14:44:57     LOG [InstanceLoader] ConfigModule dependencies initialized +1ms
[Nest] 359207  - 20/09/2024, 14:44:57     LOG [InstanceLoader] ConfigModule dependencies initialized +0ms
[Nest] 359207  - 20/09/2024, 14:44:57     LOG [InstanceLoader] UploadModule dependencies initialized +1ms
[Nest] 359207  - 20/09/2024, 14:44:57     LOG [InstanceLoader] ArmazenamentoModule dependencies initialized +0ms
[Nest] 359207  - 20/09/2024, 14:44:57     LOG [InstanceLoader] ImageKitModule dependencies initialized +1ms
[Nest] 359207  - 20/09/2024, 14:44:57     LOG [InstanceLoader] NuvemModule dependencies initialized +1ms
[Nest] 359207  - 20/09/2024, 14:44:57     LOG [RoutesResolver] AppController {/}: +32ms
[Nest] 359207  - 20/09/2024, 14:44:57     LOG [RouterExplorer] Mapped {/, GET} route +2ms
[Nest] 359207  - 20/09/2024, 14:44:57     LOG [RoutesResolver] UploadController {/upload}: +0ms
[Nest] 359207  - 20/09/2024, 14:44:57     LOG [RouterExplorer] Mapped {/upload/exemplo-simples, POST} route +1ms
[Nest] 359207  - 20/09/2024, 14:44:57     LOG [RouterExplorer] Mapped {/upload/arquivos, POST} route +0ms
[Nest] 359207  - 20/09/2024, 14:44:57     LOG [RoutesResolver] ArmazenamentoController {/armazenamento}: +0ms
[Nest] 359207  - 20/09/2024, 14:44:57     LOG [RouterExplorer] Mapped {/armazenamento, POST} route +0ms
[Nest] 359207  - 20/09/2024, 14:44:57     LOG [RouterExplorer] Mapped {/armazenamento/:nome, GET} route +1ms
[Nest] 359207  - 20/09/2024, 14:44:57     LOG [RoutesResolver] NuvemController {/nuvem}: +0ms
[Nest] 359207  - 20/09/2024, 14:44:57     LOG [RouterExplorer] Mapped {/nuvem/upload, POST} route +0ms
[Nest] 359207  - 20/09/2024, 14:44:57     LOG [RouterExplorer] Mapped {/nuvem/nome/:arquivo_nome, GET} route +0ms
[Nest] 359207  - 20/09/2024, 14:44:57     LOG [RouterExplorer] Mapped {/nuvem/id/:arquivo_id, GET} route +0ms
[Nest] 359207  - 20/09/2024, 14:44:57     LOG [NestApplication] Nest application successfully started +3ms


Enter fullscreen mode Exit fullscreen mode

4. incluir módulo nestjs para os novos endpoints

[upload-api] $ npx @nestjs/cli generate resource validacao --no-spec

Enter fullscreen mode Exit fullscreen mode
[upload-api]$ npx @nestjs/cli generate resource validacao --no-spec
? What transport layer do you use? REST API
? Would you like to generate CRUD entry points? No
CREATE src/validacao/validacao.controller.ts (234 bytes)
CREATE src/validacao/validacao.module.ts (276 bytes)
CREATE src/validacao/validacao.service.ts (93 bytes)
UPDATE src/app.module.ts (940 bytes)

Enter fullscreen mode Exit fullscreen mode

após adicionar o recurso/módulo, o terminal deverá parecer como o console abaixo.

[14:46:17] File change detected. Starting incremental compilation...

[14:46:17] Found 0 errors. Watching for file changes.

[Nest] 359539  - 20/09/2024, 14:46:18     LOG [NestFactory] Starting Nest application...
[Nest] 359539  - 20/09/2024, 14:46:18     LOG [InstanceLoader] ConfigHostModule dependencies initialized +16ms
[Nest] 359539  - 20/09/2024, 14:46:18     LOG [InstanceLoader] AppModule dependencies initialized +0ms
[Nest] 359539  - 20/09/2024, 14:46:18     LOG [InstanceLoader] ValidacaoModule dependencies initialized +1ms
[Nest] 359539  - 20/09/2024, 14:46:18     LOG [InstanceLoader] ConfigModule dependencies initialized +0ms
[Nest] 359539  - 20/09/2024, 14:46:18     LOG [InstanceLoader] ConfigModule dependencies initialized +0ms
[Nest] 359539  - 20/09/2024, 14:46:18     LOG [InstanceLoader] UploadModule dependencies initialized +1ms
[Nest] 359539  - 20/09/2024, 14:46:18     LOG [InstanceLoader] ArmazenamentoModule dependencies initialized +0ms
[Nest] 359539  - 20/09/2024, 14:46:18     LOG [InstanceLoader] ImageKitModule dependencies initialized +1ms
[Nest] 359539  - 20/09/2024, 14:46:18     LOG [InstanceLoader] NuvemModule dependencies initialized +0ms
[Nest] 359539  - 20/09/2024, 14:46:18     LOG [RoutesResolver] AppController {/}: +17ms
[Nest] 359539  - 20/09/2024, 14:46:18     LOG [RouterExplorer] Mapped {/, GET} route +2ms
[Nest] 359539  - 20/09/2024, 14:46:18     LOG [RoutesResolver] UploadController {/upload}: +0ms
[Nest] 359539  - 20/09/2024, 14:46:18     LOG [RouterExplorer] Mapped {/upload/exemplo-simples, POST} route +1ms
[Nest] 359539  - 20/09/2024, 14:46:18     LOG [RouterExplorer] Mapped {/upload/arquivos, POST} route +0ms
[Nest] 359539  - 20/09/2024, 14:46:18     LOG [RoutesResolver] ArmazenamentoController {/armazenamento}: +1ms
[Nest] 359539  - 20/09/2024, 14:46:18     LOG [RouterExplorer] Mapped {/armazenamento, POST} route +0ms
[Nest] 359539  - 20/09/2024, 14:46:18     LOG [RouterExplorer] Mapped {/armazenamento/:nome, GET} route +0ms
[Nest] 359539  - 20/09/2024, 14:46:18     LOG [RoutesResolver] NuvemController {/nuvem}: +0ms
[Nest] 359539  - 20/09/2024, 14:46:18     LOG [RouterExplorer] Mapped {/nuvem/upload, POST} route +1ms
[Nest] 359539  - 20/09/2024, 14:46:18     LOG [RouterExplorer] Mapped {/nuvem/nome/:arquivo_nome, GET} route +0ms
[Nest] 359539  - 20/09/2024, 14:46:18     LOG [RouterExplorer] Mapped {/nuvem/id/:arquivo_id, GET} route +0ms
[Nest] 359539  - 20/09/2024, 14:46:18     LOG [RoutesResolver] ValidacaoController {/validacao}: +0ms
[Nest] 359539  - 20/09/2024, 14:46:18     LOG [NestApplication] Nest application successfully started +2ms

Enter fullscreen mode Exit fullscreen mode

5. codar 1 endpoint com validação nestjs para envio de imagem png

objetivo: criar o endpoint para upload de 1 arquivo imagem png com documentação swagger.

modificar o arquivo ./src/validacao/validacao.controller.ts.

--import { Controller } from '@nestjs/common';
++import {
++  Controller,
++  HttpStatus,
++  Post,
++  UploadedFile,
++  UseInterceptors,
++} from '@nestjs/common';
++import {
++  ApiBadRequestResponse,
++  ApiBody,
++  ApiConsumes,
++  ApiOperation,
++  ApiResponse,
++  ApiTags,
++} from '@nestjs/swagger';
++import { FileInterceptor } from '@nestjs/platform-express';
import { ValidacaoService } from './validacao.service';

@Controller('validacao')
++@ApiTags('validação')
export class ValidacaoController {
  constructor(private readonly validacaoService: ValidacaoService) {}
++
++  @Post('upload/png')
++  @UseInterceptors(FileInterceptor('arquivo_png'))
++  @ApiConsumes('multipart/form-data')
++  @ApiBody({
++    schema: {
++      type: 'object',
++      properties: {
++        arquivo_png: {
++          type: 'string',
++          format: 'binary',
++        },
++      },
++    },
++  })
++  @ApiOperation({ summary: 'Upload de arquivo com armazenamento na nuvem' })
++  @ApiResponse({ status: 201, description: 'Upload de arquivo concluído.' })
++  @ApiBadRequestResponse({
++    status: HttpStatus.BAD_REQUEST,
++    description: 'PROBLEMA com a imagem png enviada.',
++  })
++  upload_png(@UploadedFile() arquivo: Express.Multer.File) {
++    return { estado: 'ok' };
++  }
}

Enter fullscreen mode Exit fullscreen mode

após salvar o arquivo ./src/validacao/validacao.controller.ts, o terminal onde esta executando a API deve parecer com o console abaixo.
Note que foi adicionado mais um endpoint Mapped {/validacao/upload/png, POST} route

[20:19:27] File change detected. Starting incremental compilation...

[20:19:27] Found 0 errors. Watching for file changes.

[Nest] 415309  - 20/09/2024, 20:19:28     LOG [NestFactory] Starting Nest application...
[Nest] 415309  - 20/09/2024, 20:19:28     LOG [InstanceLoader] ConfigHostModule dependencies initialized +16ms
[Nest] 415309  - 20/09/2024, 20:19:28     LOG [InstanceLoader] AppModule dependencies initialized +0ms
[Nest] 415309  - 20/09/2024, 20:19:28     LOG [InstanceLoader] ConfigModule dependencies initialized +1ms
[Nest] 415309  - 20/09/2024, 20:19:28     LOG [InstanceLoader] ConfigModule dependencies initialized +0ms
[Nest] 415309  - 20/09/2024, 20:19:28     LOG [InstanceLoader] UploadModule dependencies initialized +0ms
[Nest] 415309  - 20/09/2024, 20:19:28     LOG [InstanceLoader] ArmazenamentoModule dependencies initialized +0ms
[Nest] 415309  - 20/09/2024, 20:19:28     LOG [InstanceLoader] ValidacaoModule dependencies initialized +0ms
[Nest] 415309  - 20/09/2024, 20:19:28     LOG [InstanceLoader] ImageKitModule dependencies initialized +1ms
[Nest] 415309  - 20/09/2024, 20:19:28     LOG [InstanceLoader] NuvemModule dependencies initialized +0ms
[Nest] 415309  - 20/09/2024, 20:19:29     LOG [RoutesResolver] AppController {/}: +18ms
[Nest] 415309  - 20/09/2024, 20:19:29     LOG [RouterExplorer] Mapped {/, GET} route +2ms
[Nest] 415309  - 20/09/2024, 20:19:29     LOG [RoutesResolver] UploadController {/upload}: +0ms
[Nest] 415309  - 20/09/2024, 20:19:29     LOG [RouterExplorer] Mapped {/upload/exemplo-simples, POST} route +1ms
[Nest] 415309  - 20/09/2024, 20:19:29     LOG [RouterExplorer] Mapped {/upload/arquivos, POST} route +0ms
[Nest] 415309  - 20/09/2024, 20:19:29     LOG [RoutesResolver] ArmazenamentoController {/armazenamento}: +0ms
[Nest] 415309  - 20/09/2024, 20:19:29     LOG [RouterExplorer] Mapped {/armazenamento, POST} route +1ms
[Nest] 415309  - 20/09/2024, 20:19:29     LOG [RouterExplorer] Mapped {/armazenamento/:nome, GET} route +0ms
[Nest] 415309  - 20/09/2024, 20:19:29     LOG [RoutesResolver] NuvemController {/nuvem}: +0ms
[Nest] 415309  - 20/09/2024, 20:19:29     LOG [RouterExplorer] Mapped {/nuvem/upload, POST} route +0ms
[Nest] 415309  - 20/09/2024, 20:19:29     LOG [RouterExplorer] Mapped {/nuvem/nome/:arquivo_nome, GET} route +1ms
[Nest] 415309  - 20/09/2024, 20:19:29     LOG [RouterExplorer] Mapped {/nuvem/id/:arquivo_id, GET} route +0ms
[Nest] 415309  - 20/09/2024, 20:19:29     LOG [RoutesResolver] ValidacaoController {/validacao}: +0ms
[Nest] 415309  - 20/09/2024, 20:19:29     LOG [RouterExplorer] Mapped {/validacao/upload/png, POST} route +0ms
[Nest] 415309  - 20/09/2024, 20:19:29     LOG [NestApplication] Nest application successfully started +3ms

Enter fullscreen mode Exit fullscreen mode

para essa versão do endpoint e qualquer arquivo enviado o resultado será como no console abaixo.

{
  "estato": "ok"
}

Enter fullscreen mode Exit fullscreen mode

objetivo: modificar o endpoint para validar o arquivo enviado, aceitando apenas o png.

modificar o arquivo ./src/validacao/validacao.controller.ts

import {
  Controller,
++  FileTypeValidator,
  HttpStatus,
++  ParseFilePipe,
  Post,
  UploadedFile,
  UseInterceptors,
} from '@nestjs/common';
import { ValidacaoService } from './validacao.service';
import {
  ApiBadRequestResponse,
  ApiBody,
  ApiConsumes,
  ApiOperation,
  ApiResponse,
  ApiTags,
} from '@nestjs/swagger';
import { FileInterceptor } from '@nestjs/platform-express';

@Controller('validacao')
@ApiTags('validação')
export class ValidacaoController {
  constructor(private readonly validacaoService: ValidacaoService) {}

  @Post('upload/png')
  @UseInterceptors(FileInterceptor('arquivo_png'))
  @ApiConsumes('multipart/form-data')
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        arquivo_png: {
          type: 'string',
          format: 'binary',
        },
      },
    },
  })
  @ApiOperation({ summary: 'Upload de arquivo com armazenamento na nuvem' })
  @ApiResponse({ status: 201, description: 'Upload de arquivo concluído.' })
  @ApiBadRequestResponse({
    status: HttpStatus.BAD_REQUEST,
    description: 'PROBLEMA com a imagem png enviada.',
  })
--  upload_png(@UploadedFile() arquivo: Express.Multer.File) {
++  upload_png(
++    @UploadedFile(
++      new ParseFilePipe({
++        validators: [new FileTypeValidator({ fileType: 'image/png' })],
++      }),
++    )
++    arquivo: Express.Multer.File,
++  ) {
    return { estado: 'ok' };
  }
}

Enter fullscreen mode Exit fullscreen mode

foi adicionado no decorador (decorator) @UploadedFile, no parâmetro da assinatura do método upload_png, um novo objeto new ParseFilePipe que será responsável por executar as validações de arquivos enviados.
As validações são inseridas no atributo validators em seguida, e neste caso foi usado apenas o FileTypeValidator para verificar o tipo de arquivo (ver aviso abaixo).

Aviso by nestjs no tutorial sobre File upload com tradução pelo ChatGPT e links by me.

Para verificar o tipo de arquivo, a classe FileTypeValidator usa o tipo detectado pelo multer. Por padrão, o multer extrai o tipo do arquivo a partir da extensão do arquivo no dispositivo do usuário. No entanto, ele não verifica o conteúdo real do arquivo. Como os arquivos podem ser renomeados para extensões arbitrárias, considere usar uma implementação personalizada (como verificar o número mágico do arquivo) se seu aplicativo requer uma solução mais segura.

para esta versão com validação do endpoint, quando enviamos um arquivo imagem png, a resposta continuará a mesma acima.
caso envie qualquer outro tipo de arquivo, a resposta será como o json abaixo.

{
  "message": "Validation failed (expected type is image/png)",
  "error": "Bad Request",
  "statusCode": 400
}

Enter fullscreen mode Exit fullscreen mode

6. codar 1 endpoint com validação nestjs para envio de imagem jpeg

objetivo: criar o endpoint para upload de 1 arquivo imagem jpeg com documentação swagger.

modificar o arquivo ./src/validacao/validacao.controller.ts.

import {
  Controller,
  FileTypeValidator,
  HttpStatus,
  ParseFilePipe,
  Post,
  UploadedFile,
  UseInterceptors,
} from '@nestjs/common';
import { ValidacaoService } from './validacao.service';
import {
  ApiBadRequestResponse,
  ApiBody,
  ApiConsumes,
  ApiOperation,
  ApiResponse,
  ApiTags,
} from '@nestjs/swagger';
import { FileInterceptor } from '@nestjs/platform-express';

@Controller('validacao')
@ApiTags('validação')
export class ValidacaoController {
  constructor(private readonly validacaoService: ValidacaoService) {}

  @Post('upload/png')
  @UseInterceptors(FileInterceptor('arquivo_png'))
  @ApiConsumes('multipart/form-data')
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        arquivo_png: {
          type: 'string',
          format: 'binary',
        },
      },
    },
  })
  @ApiOperation({ summary: 'Upload de arquivo com armazenamento na nuvem' })
  @ApiResponse({ status: 201, description: 'Upload de arquivo concluído.' })
  @ApiBadRequestResponse({
    status: HttpStatus.BAD_REQUEST,
    description: 'PROBLEMA com a imagem png enviada.',
  })
  upload_png(
    @UploadedFile(
      new ParseFilePipe({
        validators: [new FileTypeValidator({ fileType: 'image/png' })],
      }),
    )
    arquivo: Express.Multer.File,
  ) {
    return { estado: 'ok' };
  }
++
++  @Post('upload/jpeg')
++  @UseInterceptors(FileInterceptor('arquivo_jpeg'))
++  @ApiConsumes('multipart/form-data')
++  @ApiBody({
++    schema: {
++      type: 'object',
++      properties: {
++        arquivo_jpeg: {
++          type: 'string',
++          format: 'binary',
++        },
++      },
++    },
++  })
++  @ApiOperation({ summary: 'Upload de arquivo com armazenamento na nuvem' })
++  @ApiResponse({ status: 201, description: 'Upload de arquivo concluído.' })
++  @ApiBadRequestResponse({
++    status: HttpStatus.BAD_REQUEST,
++    description: 'PROBLEMA com a imagem jpeg enviada.',
++  })
++  upload_jpeg(
++    @UploadedFile()
++    arquivo: Express.Multer.File,
++  ) {
++    return { estado: 'ok' };
++  }
}

Enter fullscreen mode Exit fullscreen mode

após salvar o arquivo ./src/validacao/validacao.controller.ts, o terminal onde esta executando a API deve parecer com o console abaixo.
Note que foi adicionado mais um endpoint Mapped {/validacao/upload/jpeg, POST} route

[20:59:39] File change detected. Starting incremental compilation...

[20:59:39] Found 0 errors. Watching for file changes.

[Nest] 418615  - 20/09/2024, 20:59:41     LOG [NestFactory] Starting Nest application...
[Nest] 418615  - 20/09/2024, 20:59:41     LOG [InstanceLoader] ConfigHostModule dependencies initialized +34ms
[Nest] 418615  - 20/09/2024, 20:59:41     LOG [InstanceLoader] AppModule dependencies initialized +1ms
[Nest] 418615  - 20/09/2024, 20:59:41     LOG [InstanceLoader] ConfigModule dependencies initialized +1ms
[Nest] 418615  - 20/09/2024, 20:59:41     LOG [InstanceLoader] ConfigModule dependencies initialized +1ms
[Nest] 418615  - 20/09/2024, 20:59:41     LOG [InstanceLoader] UploadModule dependencies initialized +1ms
[Nest] 418615  - 20/09/2024, 20:59:41     LOG [InstanceLoader] ArmazenamentoModule dependencies initialized +0ms
[Nest] 418615  - 20/09/2024, 20:59:41     LOG [InstanceLoader] ValidacaoModule dependencies initialized +1ms
[Nest] 418615  - 20/09/2024, 20:59:41     LOG [InstanceLoader] ImageKitModule dependencies initialized +1ms
[Nest] 418615  - 20/09/2024, 20:59:41     LOG [InstanceLoader] NuvemModule dependencies initialized +2ms
[Nest] 418615  - 20/09/2024, 20:59:41     LOG [RoutesResolver] AppController {/}: +42ms
[Nest] 418615  - 20/09/2024, 20:59:41     LOG [RouterExplorer] Mapped {/, GET} route +5ms
[Nest] 418615  - 20/09/2024, 20:59:41     LOG [RoutesResolver] UploadController {/upload}: +1ms
[Nest] 418615  - 20/09/2024, 20:59:41     LOG [RouterExplorer] Mapped {/upload/exemplo-simples, POST} route +1ms
[Nest] 418615  - 20/09/2024, 20:59:41     LOG [RouterExplorer] Mapped {/upload/arquivos, POST} route +0ms
[Nest] 418615  - 20/09/2024, 20:59:41     LOG [RoutesResolver] ArmazenamentoController {/armazenamento}: +1ms
[Nest] 418615  - 20/09/2024, 20:59:41     LOG [RouterExplorer] Mapped {/armazenamento, POST} route +0ms
[Nest] 418615  - 20/09/2024, 20:59:41     LOG [RouterExplorer] Mapped {/armazenamento/:nome, GET} route +1ms
[Nest] 418615  - 20/09/2024, 20:59:41     LOG [RoutesResolver] NuvemController {/nuvem}: +0ms
[Nest] 418615  - 20/09/2024, 20:59:41     LOG [RouterExplorer] Mapped {/nuvem/upload, POST} route +1ms
[Nest] 418615  - 20/09/2024, 20:59:41     LOG [RouterExplorer] Mapped {/nuvem/nome/:arquivo_nome, GET} route +0ms
[Nest] 418615  - 20/09/2024, 20:59:41     LOG [RouterExplorer] Mapped {/nuvem/id/:arquivo_id, GET} route +1ms
[Nest] 418615  - 20/09/2024, 20:59:41     LOG [RoutesResolver] ValidacaoController {/validacao}: +0ms
[Nest] 418615  - 20/09/2024, 20:59:41     LOG [RouterExplorer] Mapped {/validacao/upload/png, POST} route +1ms
[Nest] 418615  - 20/09/2024, 20:59:41     LOG [RouterExplorer] Mapped {/validacao/upload/jpeg, POST} route +1ms
[Nest] 418615  - 20/09/2024, 20:59:41     LOG [NestApplication] Nest application successfully started +4ms

Enter fullscreen mode Exit fullscreen mode

para essa versão do endpoint e qualquer arquivo enviado o resultado será como no console abaixo.

{
  "estato": "ok"
}

Enter fullscreen mode Exit fullscreen mode

objetivo: modificar o endpoint para validar o arquivo enviado, aceitando apenas o jpeg e jpg.

modificar o arquivo ./src/validacao/validacao.controller.ts

import {
  Controller,
  FileTypeValidator,
  HttpStatus,
  ParseFilePipe,
  Post,
  UploadedFile,
  UseInterceptors,
} from '@nestjs/common';
import { ValidacaoService } from './validacao.service';
import {
  ApiBadRequestResponse,
  ApiBody,
  ApiConsumes,
  ApiOperation,
  ApiResponse,
  ApiTags,
} from '@nestjs/swagger';
import { FileInterceptor } from '@nestjs/platform-express';

@Controller('validacao')
@ApiTags('validação')
export class ValidacaoController {
  constructor(private readonly validacaoService: ValidacaoService) {}

  @Post('upload/png')
  @UseInterceptors(FileInterceptor('arquivo_png'))
  @ApiConsumes('multipart/form-data')
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        arquivo_png: {
          type: 'string',
          format: 'binary',
        },
      },
    },
  })
  @ApiOperation({ summary: 'Upload de arquivo com armazenamento na nuvem' })
  @ApiResponse({ status: 201, description: 'Upload de arquivo concluído.' })
  @ApiBadRequestResponse({
    status: HttpStatus.BAD_REQUEST,
    description: 'PROBLEMA com a imagem png enviada.',
  })
  upload_png(
    @UploadedFile(
      new ParseFilePipe({
        validators: [new FileTypeValidator({ fileType: 'image/png' })],
      }),
    )
    arquivo: Express.Multer.File,
  ) {
    return { estado: 'ok' };
  }

  @Post('upload/jpeg')
  @UseInterceptors(FileInterceptor('arquivo_jpeg'))
  @ApiConsumes('multipart/form-data')
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        arquivo_jpeg: {
          type: 'string',
          format: 'binary',
        },
      },
    },
  })
  @ApiOperation({ summary: 'Upload de arquivo com armazenamento na nuvem' })
  @ApiResponse({ status: 201, description: 'Upload de arquivo concluído.' })
  @ApiBadRequestResponse({
    status: HttpStatus.BAD_REQUEST,
    description: 'PROBLEMA com a imagem jpeg enviada.',
  })
  upload_jpeg(
--    @UploadedFile()
++    @UploadedFile(
++      new ParseFilePipe({
++        validators: [new FileTypeValidator({ fileType: /jpeg|jpg/ })],
++      }),
++    )
    arquivo: Express.Multer.File,
  ) {
    return { estado: 'ok' };
  }
}

Enter fullscreen mode Exit fullscreen mode

assim como no endpoint anterior /upload/png, aqui também foi adicionado no decorador (decorator) @UploadedFile, no parâmetro da assinatura do método upload_jpeg, um novo objeto new ParseFilePipe que será responsável por executar as validações de arquivos enviados.
As validações são inseridas no atributo validators em seguida, e neste caso foi usado apenas o FileTypeValidator para verificar o tipo de arquivo.
contudo neste caso, o valor de fileType em FileTypeValidator teve uma expressão regular /jpeg|jpg/ que será processada no interpretada e validada em FileTypeValidator verifique a extensão do arquivo se é igual a jpeg ou jpg por causa do pipe adicionado.

para esta versão com validação do endpoint, quando enviamos um arquivo imagem png, a resposta continuará a mesma acima.
caso envie qualquer outro tipo de arquivo, a resposta será como o json abaixo.

{
  "message": "Validation failed (expected type is /jpeg|jpg/)",
  "error": "Bad Request",
  "statusCode": 400
}

Enter fullscreen mode Exit fullscreen mode

7. codar 1 endpoint com validação personalizada para envio de imagens

FIXME

Postgres on Neon - Get the Free Plan

No credit card required. The database you love, on a serverless platform designed to help you build faster.

Get Postgres on Neon

Top comments (0)

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more