언어·프레임워크/NestJS

[NestJS] Postman에서 이미지 업로드 테스트, 왜 400?!

DandyNow 2023. 11. 2. 17:00
728x90
반응형

1. 왜 400 에러가 오는 거지?!

REST Client(VSCODE의 extension, 스크립트를 작성하여 API를 테스트할 수 있다.)를 이용해서 파일 업로드 API를 테스트하였다. 아래는 테스트를 진행한 file-upload.http 파일이며 정상적으로 잘 작동하였다.

### 사진 업로드
POST http://localhost:3000/file-upload
Content-Type: multipart/form-data; boundary=test-file-upload

--test-file-upload
Content-Disposition: form-data; name="file"; filename="test.jpg"
Content-Type: image/jpeg

< test.jpg
--test-file-upload--

 

Postman에서도 테스트를 진행해 보았는데, 이럴 수가?! 400 에러가 왔다!

{
    "message": "Unexpected field",
    "error": "Bad Request",
    "statusCode": 400
}

 

2. Body form-data의 Key를 잘 못 넣었구나!

2.1. FileInterceptor()의 첫 번째 인수를 Key로 넣었어야!

문제는 FileInterceptor의 첫 번째 인수인 'file'을 Body form-data의 Key로 넣어야 하는데 엉뚱한 Key를 넣었기 때문에 발생한 에러였다. 아래 코드에서 주석으로 설명된 부분을 참고하자!

// app.controller.ts

import {
  Controller,
  Get,
  Post,
  UploadedFile,
  UseInterceptors,
} from '@nestjs/common';
import { AppService } from './app.service';
import { FileInterceptor } from '@nestjs/platform-express';
import { multerOption } from './multer.option';

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

  // (생략)

  @Post('file-upload')
  @UseInterceptors(FileInterceptor('file', multerOption)) // FileInterceptor의 첫번째 인수인 'file'을 Body form-data의 Key로 넣어야 한다.
  fileUpload(@UploadedFile() file: Express.Multer.File) {
    console.log(file);
    return `${file.filename}`;
  }
}

 

올바른 키를 넣었더니 [그림 1]과 같이 jpg 파일이 성공적으로 업로드되었다.

[그림 1] Key를 올바르게 넣고 테스트한 결과이다. jpg 파일이 성공적으로 업로드되었다.

 

2.2. 참고 : file-upload API 구현을 위해 함께 작성한 코드 

// multer.option.ts

import { randomUUID } from 'crypto';
import { diskStorage } from 'multer';
import { extname, join } from 'path';

export const multerOption = {
  storage: diskStorage({
    destination: join(__dirname, '..', 'uploads'),
    filename: (req, file, cb) => {
      cb(null, randomUUID() + extname(file.originalname));
    },
  }),
};
// app.module.ts

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { ServeStaticModule } from '@nestjs/serve-static';
import { join } from 'path';

@Module({
  imports: [
    ServeStaticModule.forRoot({
      rootPath: join(__dirname, '..', 'uploads'),
      serveRoot: '/uploads',
    }),
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

 

728x90
반응형