개요
쇼핑몰 API 토이 프로젝트를 진행하고 있는데 상품의 이미지 관련 서비스가 필요 했습니다. 이미지를 저장할 서버가 없기에 ImgBB에서 제공하는 API를 통해 이미지를 ImgBB에 업로드하고, 해당 이미지의 정보만 데이터베이스에 저장하려고 합니다.
우선 Multer를 사용하기 위해 프로젝트에 패키지를 설치합니다.
$ npm i -D @types/multer
단일 파일 핸들
@UseInterceptors(FileInterceptor('image'))
async uploadProduct(
@UploadedFile() image: Express.Multer.File,
) {
// ...
}
파일 핸들을 위해 NestJS에서는 인터셉터를 사용합니다.
FileInterceptor의 첫번째 매개변수에 폼 데이터의 키를 문자열 형태로 지정해줍니다. 두번째 매개변수는 Multer의 옵션 객체를 받습니다.
UploadProduct의 매개변수 image는 UploadedFile 파라미터 데코레이터를 사용합니다.
다중 파일 핸들
@UseInterceptors(FilesInterceptor('image'))
async uploadProduct(
@UploadedFiles() images: Array<Express.Multer.File>,
) {
// ...
}
단일 파일 핸들과 동일하게 인터셉터를 사용합니다.
단일 파일 핸들은 FileInterceptor를 사용했고, 다중 파일 핸들을 위해서는 FilesInterceptor를 사용해야 합니다.
단일 파일 핸들과 또 다른점은 매개변수 images가 UplodedFiles 파라미터 데코레이터를 사용한다는 점입니다.
폼 데이터의 텍스트 다루기
@Post()
@UseInterceptors(FilesInterceptor('image'))
async uploadProduct(
@GetUser() user: User,
@UploadedFiles() images: Array<Express.Multer.File>,
@Body('name') name: string,
@Body('price') price: number,
@Body('amount') amount: number,
) {
// ...
}
multipart/form-data 형식의 텍스트는 @Body 데코레이터를 이용하여 받아들일 수 있습니다.
DTO(Data Transfer Object)를 사용하는게 깔끔하지만 multipart/form-data 형식에선 사용할 수 없는 것 같습니다. (정확한 이유는 찾지 못했습니다. 이유를 아신다면 댓글로 알려주세요)
이제 이미지 서버로 활용할 ImgBB에 대해서 알아보겠습니다.
ImgBB
무료 이미지 호스팅, 무료 이미지 업로드 서비스를 제공해주는 사이트입니다. 32MB 사이즈의 크기까지 업로드 할 수 있기 때문에 간단한 토이프로젝트에서 이미지 서버로 활용하기에 좋은 것 같습니다.
먼저 ImgBB에 회원 가입하고 로그인 후, 좌측 상단의 정보 항목에서 API를 클릭합니다.
아래 사진은 본인의 API 키가 노출되는 화면입니다. 아래처럼 키가 없다면 Add API Key 버튼을 눌러 API 키를 생성하면 됩니다.
ImgBB API 호출은 POST 또는 GET 요청 메서드를 사용하여 수행할 수 있습니다. 다만 GET 요청은 허용되는 URL의 최대 길이에 제한이 있으므로 POST 요청 메서드를 선호 해야 한다고 합니다.
요청 URL은 "https://api.imgbb.com/1/upload?key=당신의_API_KEY"입니다.
@Injectable()
export class ProductService {
constructor(
@InjectRepository(Product)
private productRepository: Repository<Product>,
private readonly categoryService: CategoryService,
private readonly httpService: HttpService,
private readonly configService: ConfigService,
) {}
async uploadImage(uploadImageDto: UploadImageDto) {
const url = `${this.configService.get(
'IMGBB_URL',
)}?key=${this.configService.get('IMGBB_API_KEY')}`;
const image = uploadImageDto.image;
const formData = new FormData();
formData.append('image', Buffer.from(image.buffer), image.originalname);
const { data } = await firstValueFrom(
this.httpService.post(url, formData).pipe(
map((res) => {
return res.data;
}),
),
);
return data;
}
}
이제 포스트맨을 이용해 제 컨트롤러에 요청을 보내고 이미지가 정상적으로 ImgBB에 업로드 되는지 확인해보겠습니다.
API 문서에는 나와 있지 않지만 업로드 시 허용되는 파일 확장자는 JPG, JPEG, PNG, BMP, GIF, TIF, WEBP, HEIC, PDF 인 것 같습니다.
요청을 보내고 어플리케이션을 확인해보니 정상적으로 응답이 출력 되었습니다.
이제 위 응답 데이터들을 알맞게 데이터베이스에 적재하면 될 것 같습니다.
결과
ImgBB에 정상적으로 사진이 업로드 되었습니다.
'개발 공부 > NestJS' 카테고리의 다른 글
JWT Guard 에러 메세지 커스텀 (0) | 2023.04.03 |
---|---|
인 메모리 데이터베이스, Redis (2편) (0) | 2023.03.26 |
인 메모리 데이터베이스, Redis (1편) (0) | 2023.03.26 |
Serialize 직렬화 (0) | 2023.03.23 |
인터셉터 Interceptor (0) | 2023.03.19 |