반응형
최근 NestJS 기반으로 서버 개발을 하고 있다. S3에 사용자 프로필을 업로드해야 하는 요구사항이 있어 다음과 같이
코드를 작성하여 사용하고 있다. NestJS의 Multer 라이브러리와 Multer-S3를 활용한다. 검색을 해보면 대부분 Controller 단에서 Multer-S3 라이브러리를 불러와 업로드를 하는데, 서비스단에서 비즈니스 로직을 수행하는게 맞다고 생각하여 업로드 서비스로 구분하여 구현하였다.
[config.module.ts]
import { Global, Module } from '@nestjs/common';
import { ConfigService } from '../service/config.service';
// Make Configuration Module To Global
@Global()
@Module({
providers: [ConfigService],
exports: [ConfigService],
})
export class ConfigModule {}
[config.service.ts]
import { Injectable } from '@nestjs/common';
import * as dotenv from 'dotenv';
import * as fs from 'fs';
@Injectable()
export class ConfigService {
public readonly envConfig: { [key: string]: string };
constructor() {
const filePath = `.env.${process.env.NODE_ENV}`;
this.envConfig = dotenv.parse(fs.readFileSync(filePath));
}
getAny(key: string) {
return this.envConfig[key];
}
getString(key: string): string {
return this.envConfig[key];
}
getNumber(key: string): number {
return Number(this.envConfig[key]);
}
getBoolean(key: string): boolean {
return Boolean(this.envConfig[key]);
}
}
Config 모듈은 글로벌 모듈로 만들고 ConfigService를 Re-Export 하여 프로젝트 내 모든 모듈에서 ConfigService가 주입 가능하도록 한다.
[user.module.ts]
import { Module } from '@nestjs/common';
import { MulterModule } from '@nestjs/platform-express';
import { S3Service } from '../service/upload.service';
import { UserController } from '../controller/user.controller';
import { UserService } from '../service/user.service';
@Module({
imports: [
MulterModule.registerAsync({
useClass: S3Service,
}),
],
providers: [UserService],
controllers: [UserController],
})
export class UserModule {}
[s3.service.ts]
import { Injectable, Logger } from '@nestjs/common';
import { MulterModuleOptions, MulterOptionsFactory } from '@nestjs/platform-express';
import * as AWS from 'aws-sdk';
import * as MulterS3 from 'multer-s3';
import { ConfigService } from './config.service';
@Injectable()
export class S3Service implements MulterOptionsFactory {
private s3: any;
private readonly FILE_LIMIT_SIZE = 3145728; // 사용자 프로필 이미지는 3MB 제한
constructor(private readonly configService: ConfigService) {
this.s3 = new AWS.S3();
AWS.config.update({
accessKeyId: this.configService.getString('AWS 액세스키~~'),
secretAccessKey: this.configService.getString('AWS 시크릿 키~~'),
});
}
// CallBack 함수로, NestJS의 MulterModule에 사용될 MulterModuleOption을 리턴한다.
createMulterOptions(): MulterModuleOptions | Promise<MulterModuleOptions> {
const bucket: string = `s3 버킷 경로`;
const acl: string = 'public-read';
const multerS3Storage = MulterS3({
s3: this.s3,
bucket,
acl,
metadata: (req, file, cb) => {
cb(null, { fieldName: file.fieldname });
},
key: (req, file, cb) => {
cb(null, `${Date.now().toString()}-${file.originalname}`);
},
});
return {
storage: multerS3Storage,
fileFilter: this.fileFilter,
limits: {
fileSize: this.FILE_LIMIT_SIZE,
},
};
}
public fileFilter(req: Express.Request, file: Express.Multer.File, cb: (error: Error | null, acceptFile: boolean) => void) {
if (file.mimetype.match(/\/(jpg|jpeg|png|gif)$/)) {
cb(null, true);
} else {
Logger.log(`No! ${JSON.stringify(file)}`);
cb(new Error('unsupported file'), false);
}
}
}
반응형
'Programming > Nodejs' 카테고리의 다른 글
[NodeJS] Standalone Executable File 만들기 (0) | 2019.08.16 |
---|---|
[NodeJS] APK 파싱 (2) | 2019.06.03 |
NodeJS AES 256 암복호화 코드 (3) | 2019.06.03 |
[NestJS 기반 게시판 REST API 만들기] 3. 회원가입 및 로그인, 파라미터 검증 및 예외 처리 (6) | 2019.05.08 |
[NestJS 기반 게시판 REST API 만들기] 2. 회원가입 및 로그인 기능 을 위한 DB 연동 (3) | 2019.04.30 |