용어 : 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이다.