[NestJS] – 25. 파일


API를 생성할 때 파일과 같은 바이너리 데이터 처리를 구현해야 할 수 있습니다.

이번에는 NestJS에서 요청으로 받은 파일을 서버 내부에 업로드하는 과정에 대해 써보겠습니다.


패키지 설치

실 추가 @types/multer –dev

Express에서 파일 업로드는 파일 업로드 모듈을 제공하는 Multer 패키지에 의해 구현됩니다.

Multer는 요청과 처리기 사이의 파일을 처리하는 미들웨어입니다.

NestJS는 기본적으로 Multer도 지원합니다. TypeScript와 함께 사용하기 위해 DevDependency와 함께 다음 모듈을 설치해 보겠습니다.


요청에서 파일 받기

파일.컨트롤러.ts

@Controller('file')
export class FileController {
  constructor(private readonly fileService: FileService) {}
  
  @UseInterceptors(FileInterceptor('file'))
  @Post('upload/single')
  uploadFile(@UploadedFile() file: Express.Multer.File) {
    console.log(file)
  }

}
  • 기본적인 조작 방법은 Express와 동일합니다.
  • NestJS에서 FileInterceptor(“요청 본문 필드 이름”) 인터셉터는 요청에서 해당 필드의 파일을 선택합니다.
  • 인터셉터를 사용하려면 @UseInterceptors 데코레이터를 사용하세요.
  • 인터셉터는 요청 처리기가 클라이언트에서 전달된 인수를 수집하고 이해할 수 있도록 하는 NestJS 내장 기능입니다.
  • 인터셉터가 받은 파일은 Multer의 옵션에 따라 @UploadedFile 데코레이터가 읽습니다. 판독 결과는 파일에 저장됩니다.

콘솔을 보면 파일을 성공적으로 읽은 것을 볼 수 있습니다.

{
  fieldname: 'file',
  originalname: 'google.png',
  encoding: '7bit',
  mimetype: 'image/png',
  buffer: <Buffer 89 50 4e 47 0d ... more bytes>,
  size: 17458
}

요청에서 파일 배열 가져오기

  @UseInterceptors(FileInterceptor('files'))
  @Post('upload/array')
  uploadFiles(@UploadedFiles() files: Array<Express.Multer.File>) {
    console.log(files);
  }
  • 필드에서 여러 파일을 가져오려면 @UploadedFiles를 사용하십시오.

요청에서 여러 파일 받기

  @Post('upload/multi')
  @UseInterceptors(
    FileFieldsInterceptor((
      {
        name: 'thumbnail',
        maxCount: 1,
      },
      {
        name: 'background',
        maxCount: 1,
      },
    )),
  )
  uploadMultiFiles(
    @UploadedFiles()
    files: {
      thumbnail?: Express.Multer.File;
      background?: Express.Multer.File;
    },
  ) {
    console.log(files);
  }
}
  • 여러 필드가 있는 파일을 수신할 때 FileFieldsInterceptor를 인터셉터 유형으로 사용하고 필드와 배열의 최대 파일 수를 지정하십시오.
  • 필드별로 읽을 파일은 @UploadedFiles에 객체 형식으로 작성됩니다.


파일을 서버에 저장

이제 Multer를 통해 파일을 읽을 때 서버에 저장합니다.

/src/utils/upload/multer.config.ts

import { Injectable } from '@nestjs/common';
import * as multer from 'multer';
import * as path from 'path';
import * as fs from 'fs';
import { MulterOptionsFactory } from '@nestjs/platform-express';

@Injectable()
export class MulterConfigService implements MulterOptionsFactory {
  dirPath: string;
  constructor() {
    this.dirPath = path.join(process.cwd(), 'uploads');
    this.mkdir();
  }

  // uploads 폴더 생성
  mkdir() {
    try {
      fs.readdirSync(this.dirPath);
    } catch (err) {
      fs.mkdirSync(this.dirPath);
    }
  }

  createMulterOptions() {
    const dirPath = this.dirPath;
    const option = {
      storage: multer.diskStorage({
        destination(req, file, done) {
          //파일 저장 경로 설정
          done(null, dirPath);
        },

        filename(req, file, done) {
          // 파일명 설정
          const ext = path.extname(file.originalname);
          const name = path.basename(file.originalname, ext);
          done(null, `${name}_${Date.now()}${ext}`); //파일이름_날짜.확장자
        },
      }),
      limits: { fileSize: 10 * 1024 * 1024 }, // 용량 제한
    };
    return option;
  }
}
  • Multer 옵션을 생성하는 MulterOptionFactory 인터페이스는 서비스 클래스로 구현됩니다.
  • Uploads 폴더가 생성자에 없으면 생성됩니다.
  • createMulterOptions는 MulterOptionFactory에서 구현해야 하는 메서드입니다.
    • 저장 옵션에 저장할 파일의 경로와 이름을 설정합니다.
    • 대상은 파일 저장 경로를 지정합니다. done() 을 통해 다음 미들웨어로 전달할 수 있습니다.
    • 파일 이름은 파일 이름을 지정합니다. done() 을 통해 다음 미들웨어로 전달합니다.
    • 제한 옵션에서 파일 크기를 제한할 수 있습니다.

파일.모듈.ts

import { Module } from '@nestjs/common';
import { MulterModule } from '@nestjs/platform-express';
import { MulterConfigService } from 'src/utils/upload/multer.config';
import { FileController } from './file.controller';
import { FileService } from './file.service';

@Module({
  imports: (
    MulterModule.registerAsync({
      useClass: MulterConfigService,
    }),
  ),
  controllers: (FileController),
  providers: (FileService),
})
export class FileModule {}
  • 옵션을 적용하기 위해 이제 MulterModule을 가져와서 registerAsync로 생성한 서비스를 모듈에 등록합니다.
  • 이제부터 Multer를 통과하는 파일은 디렉토리에 저장됩니다.

파일.서비스.ts

@Injectable()
export class FileService {
  constructor() {}

  fileUpload(file: Express.Multer.File) {
    if (!file) {
      throw new BadRequestException();
    }

    return file.path;
  }
}
  • Multer를 통해 업로드된 파일이 정상적으로 업로드 되었는지 확인 후 경로를 반환하는 서비스를 작성했습니다.

파일.컨트롤러.ts

@Controller('file')
export class FileController {
  constructor(private readonly fileService: FileService) {}

  @UseInterceptors(FileInterceptor('file'))
  @Post('upload/single')
  uploadFile(@UploadedFile() file: Express.Multer.File) {
    console.log(file);
    return this.fileService.fileUpload(file);
  }

}
  • 방금 만든 서비스를 사용하여 클라이언트에 응답하는 코드를 추가했습니다.


결과


저장된 파일의 경로는 클라이언트로 반환됩니다.


콘솔로 출력하면 파일에 대한 정보가 출력되는 것을 볼 수 있습니다. 요청 처리기로 오기 전에 Multer에서 파일 업로드 및 저장 과정이 처리되었으므로 경로, 파일 이름 등이 함께 출력되는지 확인할 수 있습니다.


이미지가 서버 디렉토리에 저장되었습니다.


참조

https://docs.nestjs.com/techniques/file-upload

설명서 | NestJS – 진보적인 Node.js 프레임워크

Nest는 효율적이고 확장 가능한 서버 측 Node.js 애플리케이션을 구축하기 위한 프레임워크입니다. 프로그레시브 JavaScript를 사용하고 TypeScript로 구축되었으며 OOP(Object Oriented Programming), FP(Functional Programming) 및 FRP(Functional Reac)의 요소를 결합합니다.

docs.nestjs.com

https://devkkiri.com/post/731965a8-517f-4856-b94a-c17d9e08a16c

NestJS 파일 업로드(1) | 끼리블로그

NestJS에 파일을 업로드하는 것은 명시적입니다…

devkkiri.com