용어 : Amazon S3에서 객체(object)는 파일 또는 데이터의 집합을 의미한다. 모든 객체는 bucket 내에 있다. -> 아마존 문서에서 객체는 우리가 통상적으로 생각하는 파일이라고 보면 된다.
putObject
메소드를 이용하여 파일을 업로드 한다. 오버로딩된 putObject 메소드는 아래와 같다.
putObject(String bucketName, String key, File file) //bucket과 파일명, File을 이용하는 방식
putObject(String bucketName, String key, InputStream input, ObjectMetadata metadata) //bucket과 파일명, InputStream, 파일의 메타데이터를 이용하는 방식
putObject(PutObjectRequest putObjectRequest) // putObjectRequest를 이용하는 방식
아래 예제 코드에서는 PutObjectRequest를 넘기는 방식을 사용하였다.
@Service
@RequiredArgsConstructor
public class S3FileService {
private final AmazonS3 amazonS3Client; // 생성자 주입방식, 별도 config파일에 AmazonS3ClientBean을 생성해 두었다.
//property파일에서 bucket명을 불러오게끔 설정하였다.
//private String bucket = "버킷명";과 같이 직접 설정해도 무관하다.
@Value("${cloud.aws.s3.bucket}")
private String bucket;
//여러 개의 파일을 동시에 업로드하며 생성된 파일의 URL을 사용자에게 건네는 방식으로 메소드를 구현하였다.
public List<URL> fileUpload(List<MultipartFile> multipartFiles){
List<URL> urlList = new ArrayList<>();
multipartFiles.forEach(multipartFile -> {
String fileName = makeFileName(multipartFile); //key값으로 넘겨주기 위한 파일명 생성 메소드, 각 파일을 식별할 수 있는 고유한 값만 생성될 수 있다면 생성 방식은 개발자 재량이다.
ObjectMetadata objectMetadata = new ObjectMetadata();
objectMetadata.setContentType(multipartFile.getContentType()); //객체(파일)의 메타데이터 설정
/*
1. multipartFile로부터 데이터를 읽은 후 PutObjectRequest 객체를 생성한다.
2. 이때 파일을 외부에서 읽을 수 있도록 하기 위해 withCannedAcl을 설정한다.(개별 파일에 cannedAcl(사전 정의된 ACL)을 적용한다는 의미이다.)
3. putObject메소드를 이용해 생성된 객체를 AWS S3로 전송한다.
*/
try(InputStream inputStream = multipartFile.getInputStream()){
amazonS3Client.putObject(new PutObjectRequest(bucket, fileName, inputStream, objectMetadata)
.withCannedAcl(CannedAccessControlList.PublicRead));
}catch(IOException e){
//파일 생성 및 업로드 과정에서 발생한 예외에 대해 적절한 처리를 해준다.
throw new ResourceCreationException(ErrorCode.FILE_UPLOAD_ERROR, "Img Upload Fail");
}
//bucket으로 부터 key(file명)에 대한 url 정보를 가져온다.
urlList.add(amazonS3Client.getUrl(bucket, fileName));
});
return urlList;
}
//key(파일명) 생성전략은 개발자에 자유이다.
private String makeFileName(MultipartFile multipartFile){
String originalName = multipartFile.getOriginalFilename();
final String ext = originalName.substring(originalName.lastIndexOf("."));
final String fileName = UUID.randomUUID().toString() + ext;
return System.getProperty("user.dir") + fileName;
}
}
아마존 공식 예제 : github
listObjectsV2
를 이용하여 목록을 가져온다. 오버로딩 메소드는 아래와 같다. public ListObjectsV2Result listObjectsV2(String bucketName)
public ListObjectsV2Result listObjectsV2(String bucketName, String prefix)
public ListObjectsV2Result listObjectsV2(ListObjectsV2Request listObjectsV2Request)
아래 예제 코드에서는 bucketName만을 넘겨 모든 객체(파일) 리스트를 불러왔다.
@Service
@RequiredArgsConstructor
public class S3FileService {
private final AmazonS3 amazonS3Client; // 생성자 주입방식, 별도 config파일에 AmazonS3ClientBean을 생성해 두었다.
//property파일에서 bucket명을 불러오게끔 설정하였다.
//private String bucket = "버킷명";과 같이 직접 설정해도 무관하다.
@Value("${cloud.aws.s3.bucket}")
private String bucket;
public List<String> getFileList(){
List<String> fileList = new ArrayList<>();
ListObjectsV2Result result = s3.listObjectsV2(bucket_name);
List<S3ObjectSummary> objects = result.getObjectSummaries();
for (S3ObjectSummary os : objects) {
fileList.add(os.getKey());
}
return fileList;
}
}
아마존 공식 예제 : github
getObject
를 이용하여 객체(파일)를 가져온다.
public S3Object getObject(String bucketName, String key)
public S3Object getObject(GetObjectRequest getObjectRequest)
public ObjectMetadata getObject(final GetObjectRequest getObjectRequest, File destinationFile)
아래 예제 코드에서는 bucketName과 key(파일명)만으로 객체를 가져왔다.
@Service
@RequiredArgsConstructor
public class S3FileService {
private final AmazonS3 amazonS3Client; // 생성자 주입방식, 별도 config파일에 AmazonS3ClientBean을 생성해 두었다.
//property파일에서 bucket명을 불러오게끔 설정하였다.
//private String bucket = "버킷명";과 같이 직접 설정해도 무관하다.
@Value("${cloud.aws.s3.bucket}")
private String bucket;
public void getFile(String fileName){
try {
//S3로부터 파일 가져오기
S3Object o = s3.getObject(bucket, fileName);
//가져온 객체로부터 파일 내용 꺼내기
S3ObjectInputStream file = o.getObjectContent();
//서버에 File Stream 생성
FileOutputStream fos = new FileOutputStream(new File(fileName));
byte[] read_buf = new byte[1024];
int read_len = 0;
//파일 저장
while ((read_len = file.read(read_buf)) > 0) {
fos.write(read_buf, 0, read_len);
}
file.close();
fos.close();
} catch (AmazonServiceException e) {
예외처리
} catch (FileNotFoundException e) {
예외처리
} catch (IOException e) {
예외처리
}
}
}
아마존 공식 예제 : github
copyObject
를 이용하여 객체(파일)를 가져온다.
public CopyObjectResult copyObject(String sourceBucketName, String sourceKey,
String destinationBucketName, String destinationKey)
public CopyObjectResult copyObject(CopyObjectRequest copyObjectRequest)
아래 예제 코드에서는 bucketName과 key(파일명)만으로 객체를 이동(복사)시켰다.(기존 객체는 삭제되지 않음)
@Service
@RequiredArgsConstructor
public class S3FileService {
private final AmazonS3 amazonS3Client; // 생성자 주입방식, 별도 config파일에 AmazonS3ClientBean을 생성해 두었다.
//property파일에서 bucket명을 불러오게끔 설정하였다.
//private String bucket = "버킷명";과 같이 직접 설정해도 무관하다.
@Value("${cloud.aws.s3.bucket}")
private String bucket;
public void moveFile(String destBucket, String sourcefileName, String destFileName){
try {
amazonS3Client.copyObject(bucekt, sourceFileName, destBucket, destFileName);
} catch (AmazonServiceException e) {
에러처리
}
}
아마존 공식 예제 : github
deleteObject
를 이용하여 객체(파일)를 삭제한다.
public void deleteObject(String bucketName, String key)
public void deleteObject(DeleteObjectRequest deleteObjectRequest)
아래 예제 코드에서는 bucketName과 key(파일명)만으로 객체를 삭제한다.
@Service
@RequiredArgsConstructor
public class S3FileService {
private final AmazonS3 amazonS3Client; // 생성자 주입방식, 별도 config파일에 AmazonS3ClientBean을 생성해 두었다.
//property파일에서 bucket명을 불러오게끔 설정하였다.
//private String bucket = "버킷명";과 같이 직접 설정해도 무관하다.
@Value("${cloud.aws.s3.bucket}")
private String bucket;
public void deleteFile(String fileName){
try {
amazonS3Client.deleteObject(bucket, fileName);
} catch (AmazonServiceException e) {
에러처리
}
}
아마존 공식 예제 : github
putObject
, getObject
, copyObject
, deleteObject
이다.