-
AWS-SDK를 사용하여 S3에 업로드Infra/클라우드 2022. 8. 1. 13:56
npm Dependency aws-sdk
AWS에 있는 모든 솔루션이나 서비스들을 NodeJS 직접 사용하고 컨트롤 할 수 있도록 AWS자체에서 제공해주는 package이다. 특히 S3 라이브러리를 사용할 것이다.
@Post('upload') @UseInterceptors(FileInterceptor('image')) async uploadMediaFile(@UploadedFile() file: Express.Multer.File) { console.log(file); }
FileInterceptor('image')
의미 => Post body를 통해서 data를 백엔드에 전달할 시 form-data에서 key가 'image'인 key-value를 통해서 file 정보를 넘긴다는 의미이다.
해당 Interceptor를 사용하는 메서드는 @UploadedFile() 데코레이터를 통해서 file 정보를 받을 수 있게 된다.
uploadMediaFile와 매치된 api를 request 했을 시
@UploadedFile()통해 메서드에 전단된 인자file의 console출력 결과이다.
file자체를 AWS clouding 기술을 통해서 S3에 upload
AwsService
constructor
constructor(private readonly configService: ConfigService) { this.awsS3 = new AWS.S3({ accessKeyId: this.configService.get('AWS_S3_ACCESS_KEY'), // process.env.AWS_S3_ACCESS_KEY secretAccessKey: this.configService.get('AWS_S3_SECRET_KEY'), region: this.configService.get('AWS_S3_REGION'), }); this.S3_BUCKET_NAME = this.configService.get('AWS_S3_BUCKET_NAME'); // nest-s3 }
생성자에서 ConfigService를 의존성 주입(DI) 받아서 생성하고 있다. ConfigService는 해당 service class가 속한 module.ts의 @Module({}) 데코레이터의 imports를 통해 등록을 하면 .env 같은 file을 읽을수 있게 된다.
this.awsS3
this.awsS3 = new AWS.S3({ accessKeyId: this.configService.get('AWS_S3_ACCESS_KEY'), // process.env.AWS_S3_ACCESS_KEY secretAccessKey: this.configService.get('AWS_S3_SECRET_KEY'), region: this.configService.get('AWS_S3_REGION'), });
configService 객체의 각각의 환경변수이 다 저장되어 있다. 그래서 ConfigService 자체를 DI 받아서 위 코드와 같이 this.configService.get()을 통해서 환경변수를 가져 올 수있다.
awsS3라는 인스턴스 객체를 하나 할당을 받을 것인데, 해당 인스턴스는 AWS라는 모듈안에 S3라는 class를 통해서 생성한다.
그리고 생성시에 속성으로 accessKeyId,secretAccessKey, region 를 갖는 설정 객체를 넣어준다.
마지막으로 생성자에서 S3_BUCKET_NAME도 설정해 준다.
uploadFileToS3()
file을 upload하는 함수이다.
async uploadFileToS3( folder: string, file: Express.Multer.File, ): Promise<{ key: string; s3Object: PromiseResult<AWS.S3.PutObjectOutput, AWS.AWSError>; contentType: string; }> { try { const key = `${folder}/${Date.now()}_${path.basename( file.originalname, )}`.replace(/ /g, ''); const s3Object = await this.awsS3 .putObject({ Bucket: this.S3_BUCKET_NAME, Key: key, Body: file.buffer, ACL: 'public-read', ContentType: file.mimetype, }) .promise(); return { key, s3Object, contentType: file.mimetype }; } catch (error) { throw new BadRequestException(`File upload failed : ${error}`); } }
1.parameter
uploadFileToS3(folder: string,file: Express.Multer.File,){}
1.parameter => forder : S3에 저장이 될 때 어떤 폴더에 저장이 될지 지정하는 인자이다.
엄밀히 말하면 S3에는 폴더 개념이 아니라 link 개념을 가지고 있다.
2.parameter => file : controller를 통해 넘어오는 Express.Multer.File 타입의 data이다.
2.return 값
Promise<{ key: string; s3Object: PromiseResult<AWS.S3.PutObjectOutput, AWS.AWSError>; contentType: string; }> ... return { key, s3Object, contentType: file.mimetype };
- key : S3에 저장이 되고 나서, S3저장한 key를 의미한다.
- contentType : image 혹은 video 등이 될 수 있다.
3.const key
const key = `${folder}/${Date.now()}_${path.basename( file.originalname, )}`.replace(/ /g, '');
- file.originalname = 두번째 인자 file.의 속성 값으로 upload된 file의 이름부터 확장자까지 불러온다.
- replace(/ /g, '') = url safe하기 위해 url 뒤에 들어가는 공백을 지워주는 역학을 한다. 첫번째 인자는 정규표현식이다.
*replace() = replace()라는 메서드는 문자열 data에 대해서 특정한 글자(character)를 다른 글자로 바꿔준다.
4.const s3Object
const s3Object = await this.awsS3 .putObject({ Bucket: this.S3_BUCKET_NAME, Key: key, Body: file.buffer, ACL: 'public-read', ContentType: file.mimetype, }) .promise();
5.putObject()
try { const key = `${folder}/${Date.now()}_${path.basename( file.originalname, )}`.replace(/ /g, ''); const s3Object = await this.awsS3 .putObject({ Bucket: this.S3_BUCKET_NAME, Key: key, Body: file.buffer, ACL: 'public-read', ContentType: file.mimetype, }) .promise(); return { key, s3Object, contentType: file.mimetype }; } catch (error) { throw new BadRequestException(`File upload failed : ${error}`); }
생성자에서 생성한 인스턴스 변수 awsS3의 인스턴스 멤버 메서드로 객체를 생성한다. 설정 객체로 각각 속성 값을 지정한다.
- Key : 어떤 이름을 저장될지 설정하는 속성
- Body : file의 buffer 값을 넣는다.
Promise에 담겨서 반환하기 위해 마지막에 promise 메서드를 추가한다. 값이 성공적으로 return이 되면, upload 된 filedl 정상적으로 S3에 저장된 것이다.
DeleteS3Object()
file을 delete하는 함수이다.
async deleteS3Object( key: string, callback?: (err: AWS.AWSError, data: AWS.S3.DeleteObjectOutput) => void, ): Promise<{ success: true }> { try { await this.awsS3 .deleteObject( { Bucket: this.S3_BUCKET_NAME, Key: key, }, callback, ) .promise(); return { success: true }; } catch (error) { throw new BadRequestException(`Failed to delete file : ${error}`); } }
deletObject()
delete 역시 awsS3인스턴스의 멤버 메서드를 사용하여, S3에 올라간 특정 file을 삭제할 수 있다.
삭제할 s3Object에 bucket name과 key를 속성으로 갖는 object를 첫번째 인자로 넣고, 두번째 인자로 정상적으로 삭제가 진행 되지 않을 시 발생할 error와 정상적으로 삭제가 되었을때 받게되는 data를 가진 callback 함수를 넣는다.
S3의 file 삭제
저장된 key를 지우고 싶다면, S3에 file을 upload할 시에 반환 받은 key값을 DeleteS3Object()메서드에 넣으면 된다.
즉 DB의 image field에 특정file과 매칭된 key값을 저장해둔다. key값만 알면 해당하는 S3위치로 가서 file정보들을 다 가져올 수 있다.
getAwsS3FileUrl()
public getAwsS3FileUrl(objectKey: string) { return `https://${this.S3_BUCKET_NAME}.s3.amazonaws.com/${objectKey}`; }
file이 어디에 저장되어 있는지를 알려주는 매칭 key를 인자 objectKey로 받아 file이 저장된 전체 url 소스 return한다.
Amazon S3
'Infra > 클라우드' 카테고리의 다른 글
AWS - CLI 설치 및 간단히 사용해 보기 (0) 2023.08.05 AWS - ROOT사용자 MFA적용하기, IAM admin사용자 추가 (0) 2022.12.24 AWS - Global Infrastructure Component 간략 설명 (0) 2022.12.24 AWS 클라우드 컴퓨팅 & S3 구축 (0) 2022.07.31 클라우드 컴퓨팅 설정 - 리눅스 설치 (0) 2022.04.30