20230627 TIL Nestjs에서 S3로 이미지 업로드하기
어제 파일 업로드를 위해 S3로 버켓도 만들고 IAM 사용자와 엑세스키도 발급 받았다!! 그럼 이제 nest js 에서 이미지 업로드를 위한 라이브러리를 설치하고 코드를 작성해야 한다.
npm i @types/multer aws-sdk
1. controller
컨트롤러에서 @UseInterceptors() 데코레이터를 사용해서 요청받은 파일을 받아온다. 이때 요청 파일의 key 값을 FileInterceptor() 안에 넣어준다. 나는 프론트에서 Image라는 키값으로 보내주기 때문에 @UseInterceptors(FileInterceptor('Image')) 라고 작성해주었다.
@Post()
@UseInterceptors(FileInterceptor('Image'))
async uploadFile(@UploadedFile() Image: Express.Multer.File): Promise<object> {
//업로드 파일정보
const bucketName = configService.get('AWS_BUCKET_NAME');
const key = Image.originalname;
const fileData = Image.buffer;
return this.fundingService.createFunding(
bucketName,
key,
fileData,
);
}
function 이름은 무조건 uploadFile로 해야한다. 다른걸로 해보려고 했는데 바꾸라는 에러 메세지가 발생했다. Image를 콘솔로 찍어보면 여러 데이터가 들어가 있는데 여기서 key값과 buffer 값을 이용해서 s3에 저장할 때 사용할 것이다. 이때 bucketName에 들어가는 값은 S3에서 생성해둔 버켓의 이름이다.
2. service
서비스 계층에서는 먼저 aws-sdk 에서 S3를 import 해주어야 한다.
import { S3 } from 'aws-sdk';
S3에 저장이 완료되면 db에도 정보를 저장해두어야 하기 때문에 Resource entity를 인젝트 해둔다. constructor 생성자 내부에 AWS 인증 정보를 설정해주어야 한다. 나는 어쩌다보니 S3의 region이 글로벌로 설정이 되어 있어서 region:null로 해두었지만 글로벌로 되어있지 않을 때에는 각 region에 맞는 값을 입력해주어야 한다.
export class FundingService {
private s3: S3;
constructor(
@InjectRepository(Resource)
private accountRepository: Repository<Resourc>,
) {
// AWS 인증 정보 설정
this.s3 = new S3({
accessKeyId: configService.get('AWS_ACCESS_KEY'),
secretAccessKey: configService.get('AWS_SECRET_KEY'),
region: null, // AWS S3 버킷이 위치한 리전
});
}
이제 모든 설정에 관련된 것들은 다 끝났다!! 실제 S3에 업로드 하는 부분의 코드는 아래에 있다. 컨트롤러 계층에서 입력받은 bucketname과 key, buffer를 객체로 만든 후 upload() 를 사용해서 업로드해주면 끝이다!
async createFunding(
bucketName: string,
key: string,
fileData: Buffer,
): Promise<object> {
//s3 업로드
const uploadParams = {
Bucket: bucketName,
Key: key,
Body: fileData,
};
const uploadResult = await this.s3.upload(uploadParams).promise();
}
nest.js에서 s3사용하는 방법이 node.js에서 사용하는 방법보다 더 간단한 것 같다.