NestJS | 파일 업로드 API

Stellar·2021년 8월 16일
0

JS Runtime

목록 보기
7/13
post-thumbnail

## 업로드 파일 삭제 API 구현 바로가기


# 기초 세팅

NestJS-프로젝트 세팅

파일 업로드 - NestJS 공식문서

## Multer 설치

Multer
파일 업로드를 위해 사용되는 multipart/form-data를 다루기 위한 node.js 의 미들웨어이다.
Multermultipart (multipart/form-data)가 아닌 폼에서는 동작하지 않는다.
참고 - nodejs 파일 업로드 - multer 모듈

$ npm i -D @types/multer

# MulterOptions 로직 구현

multer를 사용하여 파일을 업로드할 때 경로, 파일 형식, 갯수, 파일 이름등을 지정할 수 있도록 Multer Option을 설정해준다.
참고 - multerOptions - expressjs

KeyDescription
dest or storage파일이 저장될 위치
fileFilter어떤 파일을 허용할지 제어하는 함수
limits업로드 된 데이터의 한도
preservePath파일의 base name 대신 보존할 파일의 전체 경로

## 파일 형식 기능 검사하기

### 하나의 형식만 검사

//src/lib/muterOptions.ts
export const multerOptions = {
    fileFilter: (request, file, cb) => {
        if (file.mimetype.match('image/jpeg')) {
            cb(null, true);
        } else {
            cb(new Error('지원하지 않는 이미지 형식입니다.'));
        }
    }
}

### 여러 파일 형식 검사

//src/lib/muterOptions.ts
export const multerOptions = {
    fileFilter: (request, file, cb) => {
        if (file.mimetype.match(/\/(jpg|jpeg|png|gif)$/)) {
            cb(null, true);
        } else {
            cb(new Error('지원하지 않는 이미지 형식입니다.'));
        }
    }
}

### 파일, 사진 등으로 분류

//src/lib/muterOptions.ts
export const multerOptions = {
    fileFilter: (request, file, cb) => {
        if (file.mimetype.match('image.*|text.*|application.*')) {
            cb(null, true);
        } else {
            cb(new Error('지원하지 않는 파일 형식입니다.'));
        }
    }
}
  • cb : callback
  • file은 console로 확인 시 아래와 같은 정보를 전달해준다.
{
  fieldname: 'file',
  originalname: 'jpegfile.jpeg',
  encoding: '7bit',
  mimetype: 'image/jpeg',
  buffer: <Buffer ff ... 6013 more bytes>,
  size: 6063
}

## 저장 위치 지정

현재 프로젝트 폴더를 기준으로 파일이 생성되므로 AWS의 인스턴스나 S3등을 활용해 파일을 브라우저에서 불러올 수 있도록 할 수 있다.

//src/lib/muterOptions.ts
import { existsSync, mkdirSync } from "fs";
import { diskStorage } from "multer";

export const multerOptions = {
    fileFilter: (request, file, cb) => {
        ...
    },
    
    storage: diskStorage({
        destination: (request, file, cb) => {
            //upload 경로 지정
            const uploadPath: string = 'public';
            
			
            //경로가 없을 시 폴더 생성
            if (!existsSync(uploadPath)) {
                mkdirSync(uploadPath);
            
            }
            cb(null, uploadPath);
        }
    })
}

Public 폴더가 생성된 후 파일이 업로드 되었다.


## 파일 이름 지정하여 업로드 하기

저장한 파일의 이름이 보안으로인해 변경 되므로 어떤 형태로 저장할지 코드를 구현

### 원본 사진 이름 그대로 저장

//src/lib/muterOptions.ts
...
    storage: diskStorage({
        ...
        },

        filename: (request, file, cb) => {
            cb(null, file.originalname)
        }
    })
}


### UUID 저장 (구현 전)


# BASIC 파일 업로드 로직 구현

## controller 작성

하나의 파일만 업로드가 가능한 코드를 작성.
Interceptors 데코레이터를 사용하여 form-data로 전송된 파일이 MulterOption에 적합한지 검사를 한다.
참고 - Interceptor 사용법 - 하루사리

// app.controller.ts
import { Controller, Get, Post, UploadedFile, UseInterceptors } from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express';
import { AppService } from './app.service';
import { multerOptions } from './lib/multerOptions';

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

  @Get()
  getHello(): string {
    return this.appService.getHello();
  }

  //form-data key 값, multer 옵션 파일 연결
  @UseInterceptors(FileInterceptor('file', multerOptions))
  @Post('upload')
  uploadFile(
    @UploadedFile() file: Express.Multer.File) 
    {
    console.log(file)
    return 'FILE_UPLOAD_SUCCESS'
  }
}

## 기능 테스트


# ARRAY 파일 업로드 로직 구현 (여기 진행하기)

여러 파일을 배열 형태로 업로드가 가능한 코드를 작성.
Interceptors 데코레이터를 사용하여 form-data로 전송된 파일이 MulterOption에 적합한지 검사를 한다.
참고 - Interceptor 사용법 - 하루사리

// app.controller.ts
import { Controller, Post, UploadedFiles, UseGuards, UseInterceptors } from '@nestjs/common';
import { FilesInterceptor } from '@nestjs/platform-express';
import { multerOptions } from 'lib/multerOptions';
import UploadService from './upload.service';
import AuthGuard from 'middleware/auth';

@Controller('uploads')
export default class UploadController {
  constructor(
    private readonly uploadService: UploadService,
  ) {}

  @UseInterceptors(FilesInterceptor('images', null, multerOptions))
  // FilesInterceptor 첫번째 매개변수: formData의 key값,
  // 두번째 매개변수: 파일 최대 갯수
  // 세번째 매개변수: 파일 설정 (위에서 작성했던 multer 옵션들)
  
  @Post('/')
  @UseGuards(new AuthGuard())
  public uploadFiles(
    @UploadedFiles() files: File[],
  ) {
    const uploadedFiles: string[] = this.uploadService.uploadFiles(files);

    return {
      status: 200,
      message: '파일 업로드를 성공하였습니다.',
      data: {
        files: uploadedFiles,
      },
    };
  }
}
  • FileInterceptor('form-data key 값', 파일 최대 갯수, multerOptions)
  • multerOptions : multerOptions.ts 파일에서 작성한 옵션을 사용하기위해 적어준다.

참고


토끼굴

  • 리팩토링하면서 파일 하나만 업로드 시 포스트맨으로 파일 여러개 선택 가능한지 확인하기

0개의 댓글