Logo

dev-resources.site

for different kinds of informations.

NestJS - criar um endpoint para upload de diversos arquivos

Published at
9/15/2024
Categories
infoweb
nestjs
upload
typescript
Author
leonardominora
Categories
4 categories in total
infoweb
open
nestjs
open
upload
open
typescript
open
Author
14 person written this
leonardominora
open
NestJS - criar um endpoint para upload de diversos arquivos

Informações gerais

objetivo

  • criar 1 endpoint para API de upload de múltiplos arquivos

notas de aula

sumário

  1. pegar o código do projeto anterior
  2. executar a API
  3. criar e configurar 1 endpoint para receber vários arquivos
  4. criar método no serviço para retornar as informações dos arquivos

para receber vários arquivos, o nestjs disponibiliza os seguintes interceptors:

  • FilesInterceptor - identifica um array de arquivos com o mesmo nome de campo do formulário;
  • FileFieldsInterceptor -
  • AnyFilesInterceptor -

1. pegar o código do projeto anterior

a nota de aula anterior é NestJS - Upload de 1 arquivo que criou um projeto javascript para uma API Rest usando nestjs e typescript.

pode utilizar o seu próprio código, ou baixar o zip ou fazer o clone do repositório github.

2. Executar a API

lembre de acessar a pasta do projeto!!!

antes de executar a api, lembrar de instalar as bibliotecas do projeto com o comando npm i.

lançar a api em modo desenvolvimento executando o comando npm com a opção run para executar o script start:dev.

[upload-api] $ npm run start:dev

Enter fullscreen mode Exit fullscreen mode

a execução deverá produzir um resultado parecido com o console abaixo.

[11:58:35] Starting compilation in watch mode...

[11:58:37] Found 0 errors. Watching for file changes.

[Nest] 12346  - 15/09/2024, 11:58:38     LOG [NestFactory] Starting Nest application...
[Nest] 12346  - 15/09/2024, 11:58:38     LOG [InstanceLoader] AppModule dependencies initialized +14ms
[Nest] 12346  - 15/09/2024, 11:58:38     LOG [InstanceLoader] UploadModule dependencies initialized +1ms
[Nest] 12346  - 15/09/2024, 11:58:38     LOG [RoutesResolver] AppController {/}: +15ms
[Nest] 12346  - 15/09/2024, 11:58:38     LOG [RouterExplorer] Mapped {/, GET} route +3ms
[Nest] 12346  - 15/09/2024, 11:58:38     LOG [RoutesResolver] UploadController {/upload}: +0ms
[Nest] 12346  - 15/09/2024, 11:58:38     LOG [RouterExplorer] Mapped {/upload/exemplo-simples, POST} route +2ms
[Nest] 12346  - 15/09/2024, 11:58:38     LOG [NestApplication] Nest application successfully started +4ms

Enter fullscreen mode Exit fullscreen mode

3. criar e configurar 1 endpoint para receber vários arquivos

adicionar um endpoint no controller src/upload/upload.controller.ts, atualizando as importações, conforme código (diff) abaixo.

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

@Controller('upload')
@ApiTags('upload')
export class UploadController {
  constructor(private readonly uploadService: UploadService) {}

  @Post('exemplo-simples')
  @UseInterceptors(FileInterceptor('arquivo'))
  @ApiConsumes('multipart/form-data')
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        arquivo: {
          type: 'string',
          format: 'binary',
        },
      },
    },
  })
  @ApiOperation({ summary: 'Exemplo de upload de 1 arquivo qualquer' })
  @ApiResponse({ status: 201, description: 'Arquivo enviado com sucesso.' })
  @ApiResponse({ status: 400, description: 'Erro no envio do arquivo.' })
  uploadArquivoSimples(@UploadedFile() arq: Express.Multer.File) {
    console.log(arq);

    return this.uploadService.responderInformacaoArquivo(arq);
  }

++  @Post('arquivos')
++  @UseInterceptors(FilesInterceptor('arquivos'))
++  @ApiConsumes('multipart/form-data')
++  @ApiBody({
++    schema: {
++      type: 'object',
++      properties: {
++        arquivos: {
++          type: 'array',
++          items: {
++            type: 'string',
++            format: 'binary',
++          },
++        },
++      },
++    },
++  })
++  @ApiResponse({
++    status: 201,
++    description: 'Arquivo(s) enviado(s) com sucesso.',
++  })
++  @ApiBadRequestResponse({
++    status: 400,
++    description: 'Erro no envio de arquivos.',
++  })
++  uploadArquivos(@UploadedFiles() arquivos: Array<Express.Multer.File>) {
++    return {
++      estado: 'ok',
++      data: {
++        quantidade: arquivos?.length,
++      },
++    };
++  }
}

Enter fullscreen mode Exit fullscreen mode

foi adicionado nas importações o interceptor FilesInterceptor e o decorator UploadedFiles responsáveis por interceptar e extrair vários arquivos em uma array nomeada como arquivos no formulário.

o decorator @Post configura o verdo POST e o path arquivos do endpoint.
enquanto o decorator @UseInterceptors configura o uso do FilesInterceptor para interceptar a requisitação HTTTP(S) a procura da variável arquivos dentro do formulário no corpo da mensagem.

as próximas linhas contém os decorators @Api (ApiConsumes, ApiBody, ApiResponse, e ApiBadRequestResponse) para configurar a documentação do swagger.

a próxima linha, uploadArquivos(@UploadedFiles() arquivos: Array<Express.Multer.File>) especifica o método uploadArquivos.
este método tem como parâmetro a variável arquivos que irá receber um array contendo itens cada tipados com Express.Multer.File.
o parâmetro arquivos também esta decorado com UploadedFiles que é responsável por extrair o array de arquivos da mensagem HTTP.

ao salvar, a api será relançada e o terminal onde ela esta sendo executada deverá ficar como o console abaixo.

[11:58:35] Starting compilation in watch mode...

[11:58:37] Found 0 errors. Watching for file changes.

[Nest] 12346  - 15/09/2024, 11:58:38     LOG [NestFactory] Starting Nest application...
[Nest] 12346  - 15/09/2024, 11:58:38     LOG [InstanceLoader] AppModule dependencies initialized +14ms
[Nest] 12346  - 15/09/2024, 11:58:38     LOG [InstanceLoader] UploadModule dependencies initialized +1ms
[Nest] 12346  - 15/09/2024, 11:58:38     LOG [RoutesResolver] AppController {/}: +15ms
[Nest] 12346  - 15/09/2024, 11:58:38     LOG [RouterExplorer] Mapped {/, GET} route +3ms
[Nest] 12346  - 15/09/2024, 11:58:38     LOG [RoutesResolver] UploadController {/upload}: +0ms
[Nest] 12346  - 15/09/2024, 11:58:38     LOG [RouterExplorer] Mapped {/upload/exemplo-simples, POST} route +2ms
[Nest] 12346  - 15/09/2024, 11:58:38     LOG [NestApplication] Nest application successfully started +4ms

Enter fullscreen mode Exit fullscreen mode

para testar, use a documentação da api acessando o endereço http://localhost:3000/docs/
clique no botão Try it out, escolher alguns arquivos, e clicar em Execute.
a operação deve estar semelhante com a figura abaixo e o resultado após a execução com o json abaixo da figura.

Image description

{
  "estado": "ok",
  "data": {
    "quantidade": 3
  }
}

Enter fullscreen mode Exit fullscreen mode

4. criar método no serviço para retornar as informações dos arquivos

no arquivo src/upload/upload.service.ts crie o método responderInformacoesArquivos(arquivos: Array<Express.Multer.File>) e coloque a implementação conforme arquivo (diff) abaixo.

import { Injectable } from '@nestjs/common';

@Injectable()
export class UploadService {
  responderInformacaoArquivo(arquivo: Express.Multer.File) {
    return {
      estado: 'ok',
      dados: {
        nome: arquivo.originalname,
        tamanho: arquivo.size,
        mimetype: arquivo.mimetype,
        encode: arquivo.encoding,
      },
    };
  }
++
++  responderInformacoesArquivos(arquivos: Array<Express.Multer.File>) {
++    const informacoes = arquivos.map((arquivo) => {
++      return {
++        nome: arquivo.originalname,
++        tamanho: arquivo.size,
++        mimetype: arquivo.mimetype,
++        encode: arquivo.encoding,
++      };
++    });
++    return {
++      estado: 'ok',
++      dados: {
++        quantidade: arquivos?.length,
++        arquivos: informacoes,
++      },
++    };
++  }
}
Enter fullscreen mode Exit fullscreen mode

após a modificação do service terá de modificar o controller no arquivo src/upload/upload.controller.ts conforme arquivo abaixo para chamar o método responderInformacoesArquivos.

import {
  Controller,
  Post,
  UploadedFile,
  UploadedFiles,
  UseInterceptors,
} from '@nestjs/common';
import { FileInterceptor, FilesInterceptor } from '@nestjs/platform-express';
import {
  ApiBadRequestResponse,
  ApiBody,
  ApiConsumes,
  ApiOperation,
  ApiResponse,
  ApiTags,
} from '@nestjs/swagger';
import { UploadService } from './upload.service';

@Controller('upload')
@ApiTags('upload')
export class UploadController {
  constructor(private readonly uploadService: UploadService) {}

  @Post('exemplo-simples')
  @UseInterceptors(FileInterceptor('arquivo'))
  @ApiConsumes('multipart/form-data')
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        arquivo: {
          type: 'string',
          format: 'binary',
        },
      },
    },
  })
  @ApiOperation({ summary: 'Exemplo de upload de 1 arquivo qualquer' })
  @ApiResponse({ status: 201, description: 'Arquivo enviado com sucesso.' })
  @ApiResponse({ status: 400, description: 'Erro no envio do arquivo.' })
  uploadArquivoSimples(@UploadedFile() arq: Express.Multer.File) {
    console.log(arq);

    return this.uploadService.responderInformacaoArquivo(arq);
  }

  @Post('arquivos')
  @ApiConsumes('multipart/form-data')
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        arquivos: {
          type: 'array',
          items: {
            type: 'string',
            format: 'binary',
          },
        },
      },
    },
  })
  @ApiResponse({
    status: 201,
    description: 'Arquivo(s) enviado(s) com sucesso.',
  })
  @ApiBadRequestResponse({
    status: 400,
    description: 'Erro no envio de arquivos.',
  })
  @UseInterceptors(FilesInterceptor('arquivos'))
  uploadArquivos(@UploadedFiles() arquivos: Array<Express.Multer.File>) {
--    return {
--      estado: 'ok',
--      dados: {
--        quantidade: arquivos?.length,
--        arquivos: informacoes,
--      },
--    };
++    return this.uploadService.responderInformacoesArquivos(arquivos);
  }
}

Enter fullscreen mode Exit fullscreen mode

para testar, pode usar novamente a documentação da API conforme a figura anterior.
o resultado agora será parecido conforme o json abaixo.

{
  "estado": "ok",
  "dados": {
    "quantidade": 3,
    "arquivos": [
      {
        "nome": "README.md",
        "tamanho": 1373,
        "mimetype": "text/markdown",
        "encode": "7bit"
      },
      {
        "nome": "package.json",
        "tamanho": 2020,
        "mimetype": "application/json",
        "encode": "7bit"
      },
      {
        "nome": "Captura de tela de 2024-09-15 15-35-33.png",
        "tamanho": 44726,
        "mimetype": "image/png",
        "encode": "7bit"
      }
    ]
  }
}

Enter fullscreen mode Exit fullscreen mode

Referência e link

upload Article's
30 articles in total
Favicon
UploadThing: A Modern File Upload Solution for Next.js Applications
Favicon
NestJS - Armazenamento nas nuvens
Favicon
NestJS - criar um endpoint para upload de diversos arquivos
Favicon
NestJS - Validando o envio de arquivos
Favicon
NestJS - Armazenamento local de upload
Favicon
NestJS - criar endpoint para upload de 1 arquivo
Favicon
Next.js: Upload de imagem para a Cloudflare R2 Utilizando Presigned URL
Favicon
A file uploader built with shadcn/ui and react-dropzone
Favicon
Elevate Your GraphQL API: Mastering File Uploads with Yoga GraphQL
Favicon
Mastering File Uploads in Laravel 11: A Comprehensive Guide
Favicon
How To Upload Multiple File In Laravel 10
Favicon
Different approaches to reduce AWS S3 file upload time using AWS-SDK v3 in NodeJS.
Favicon
How would you handle image upload?
Favicon
Upload File di Node JS
Favicon
Uploading Images with Node.js and React.js
Favicon
Simplifying AWS S3 File Uploads with the Android Library
Favicon
Laravel 10 Crop Image Before Upload Cropper Js
Favicon
Enhance Job Seeker Experience: Quick Image Upload for Portals
Favicon
A file upload sample with NextJs
Favicon
Azure Storage Account: Unleash the Potential of Cloud-Based Storage
Favicon
Spheron Network: Browser Upload
Favicon
Uploading files from terminal on file hosting service, and unlimited cloud storage
Favicon
Process FormData file sent to Node server
Favicon
Express file upload using Multer
Favicon
Maximize Your Client Upload Efficiency with the Bulk Upload
Favicon
Upload images in Ckeditor 5 with Laravel
Favicon
Eteot Logo
Favicon
Install & Upload WordPress Plugin
Favicon
Laravel 9 Multiple Image Upload Example
Favicon
How To Enhance JavaScript File Upload In Your Web App

Featured ones: