지난 번 S3에 어떻게 접근하는지는 파악했으므로, 본격적으로 코드 수정을 했다.
구글링 결과 대부분의 블로그는 파일 업로드에 대해서만 언급을 하고, 직접적인 조작에 대해서는 만족할 만한 자료를 찾을 수 없었다.
https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html
위 링크는 AWS에서 제공하는 aws-sdk 공식문서. 위 자료를 많이 참고했다.
AWS에서는 S3에 저장되는 파일을 객체라 표현한다. S3에 파일을 저장할 때 파일 자체의 버퍼 뿐만 아니라 메타데이터도 함께 저장을 하기 때문인 것으로 짐작한다.
sdk 내에 폴더 조작에 대한 메서드는 없다. 다만 객체 이름에 들어가는 후행문자 /로 폴더를 구분해준다. 객체 생성 시 key를 "uploads/file.txt"로 작성하면 자동으로 uploads라는 폴더를 생성하고, 그 안에 객체를 저장한다.
sdk 내에 있는 메서드를 동기적으로 실행하기 위해 await 키워드를 사용했다. 대신 메서드의 끝에 메서드 체인으로 .promise()을 사용해야 한다.
getObject() 메서드를 사용한다.
const aws = require("aws-sdk");
const s3 = new aws.S3();
const result = await s3.getObject({
Bucket: "버킷 이름",
Key: "path/to/file",
}).promise();
존재할 때 결과
copyObject() 메서드를 사용한다.
await s3.copyObject({
Bucket: "버킷 이름",
CopySource: `버킷 이름/${url}`,
Key: `uploads/content/${filename}`,
ACL: "public-read",
})
.promise();
CopySource에 주목할 것. CopySource에는 root에서의 경로가 아니라, 버킷 이름까지 포함 시켜야 한다.
deleteObject() 메서드를 사용한다.
await s3
.deleteObject({
Bucket: "버킷 이름",
Key: "path/to/obj/objname",
}).promise();
const listParams = {
Bucket: "버킷 이름",
Prefix: "uploads/temp",
};
const listedObjects = await s3.listObjectsV2(listParams).promise();
// 폴더 내 파일이 없으면 함수 종료
if (listedObjects.Contents.length === 0) return;
const deleteParams = {
Bucket: "버킷 이름",
Delete: { Objects: [] },
};
listedObjects.Contents.forEach(({ Key }) => {
deleteParams.Delete.Objects.push({ Key });
});
await s3.deleteObjects(deleteParams).promise();
uploads/temp 라는 폴더의 내용물을 지우는 코드다.
aws-sdk에서는 node fs 모듈의 rm("url" , { recursive : true }); 에 대응하는 메서드를 찾을 수 없었다.
uploads/temp 폴더안의 객체들을 검색한다. -> 검색된 객체들에 대해 반복문을 돌린다 -> 삭제할 파일들을 deleteParams 내 Objects 배열 안으로 넣는다. -> deleteObjects() 메서드를 실행한다.
위에서 언급했듯이, 폴더 조작에 대한 메서드는 없다. 폴더 안의 내용물을 모두 삭제할 경우, 해당 폴더는 자동으로 삭제된다.
한글이 들어간 파일을 S3에 업로드할 경우, S3 콘솔에서는 한글을 출력하지만 , node에서 해당 객체를 읽을 경우 인코딩된 문자열이 나온다.
따라서 본인의 코드 구현 시 디코딩이 필요한 경우가 생긴다. 필요에 따라 decodeURIComponent()를 사용하도록 하자.