<!-- https://mvnrepository.com/artifact/com.amazonaws/aws-java-sdk-s3 --> <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-java-sdk-s3</artifactId> <version>1.12.389</version> </dependency>
연동에 필요한 정보들을 properties 파일에 작성
리전은 생성된 버킷 페이지에서 확인할 수 있는데, 한국이면 보통 ap-northeast-2입니다 참고
cloud.aws.credentials.accessKey=액세스 키 cloud.aws.credentials.secretKey=시크릿 키 cloud.aws.stack.auto=false cloud.aws.s3.bucket=버킷명 cloud.aws.region=리전 cloud.aws.s3.bucket.url=https://s3.리전.amazonaws.com/버킷명
설정파일 작성
@Configuration @EnableWebMvc @PropertySource("classpath:props/fileUpload.properties") public class AWSConfiguration implements WebMvcConfigurer{ @Value("${cloud.aws.credentials.accessKey}") private String accessKey; @Value("${cloud.aws.credentials.secretKey}") private String secretKey; @Value("${cloud.aws.region}") private String region; @Bean public AmazonS3Client awsS3Client() { BasicAWSCredentials awsCredentials = new BasicAWSCredentials(accessKey, secretKey); AmazonS3Client s3Builder = (AmazonS3Client)AmazonS3ClientBuilder.standard() .withRegion(region) .withCredentials(new AWSStaticCredentialsProvider(awsCredentials)) .build(); return s3Builder; } }
코드의 흐름은 다음과 같습니다
@PropertySource 어노테이션으로 작성한 properties파일의 값을 가져옵니다
액세스 키, 시크릿 키와 같은 중요 정보들을 환경변수로 다루기 위함입니다.withRegion(Regions.AP_NORTHEAST_2)
region은 프로퍼티 파일에 입력하지 않고 위 형태처럼 Regions의 enum을 통해 값을 입력할 수도 있습니다 참고
AWSCredentials
의 구현체인BasicAWSCredentials
클래스를 생성합니다
생성자에 액세스 키, 시크릿 키를 전달합니다
AWSCredentials
인터페이스는 액세스 키, 시크릿 키에 대한 액세스를 제공하는 역할을 합니다 (자격 증명 공급자)
S3 서비스에 액세스하기 위한
AmazonS3Client
클래스를AmazonS3ClientBuilder
를 통해 구현합니다
아마존에서는 AmazonS3Client클래스에 생성자를 사용하는 것보다 AmazonS3ClientBuilder를 사용하는 것을 권장하고 있습니다
standard()
로 모든 기본값이 설정된 builder 인스턴스 생성withRegion()
메소드의 매개변수로 리전 전달withCredentials()
메소드의 매개변수로AWSStaticCredentialsProvider
객체를 전달 (BasicAWSCredentials를 매개변수로 직접 사용하지 않고, AWSStaticCredentialsProvider 객체의 생성자에 전달해 BasicAWSCredentials를 래핑하기 위함)build()
로 S3 클라이언트 빌드
4. 마지막으로 @Bean 어노테이션을 사용해 반환된 AmazonS3Client 객체를 빈으로 등록합니다
@Service
@PropertySource("classpath:props/fileUpload.properties")
public class ProductFileService {
private static final Logger logger = LoggerFactory.getLogger(ProductController.class);
@Autowired
private AmazonS3 s3Client;
@Value("${cloud.aws.s3.bucket}")
private String bucket;
public String getPath() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd/");
return sdf.format(new Date());
}
public String getUUID() {
return UUID.randomUUID().toString();
}
public boolean delete(List<String> keyList) throws Exception{
int rowCnt = 0;
for(String key : keyList) {
DeleteObjectRequest deleteObjectRequest = new DeleteObjectRequest(this.bucket, key);
this.s3Client.deleteObject(deleteObjectRequest);
logger.info("delete complete! {}", deleteObjectRequest.getKey());
rowCnt++;
}
return rowCnt == keyList.size() ? true : false;
}
public List<ProductFileDto> upload(List<MultipartFile> file, String product_no) throws Exception{
List<ProductFileDto> list = new ArrayList<>();
int idx = 0;
for(MultipartFile multipartFile : file) {
byte[] bytes = IOUtils.toByteArray(multipartFile.getInputStream());
String originalName = multipartFile.getOriginalFilename();
String uuid = getUUID();
ObjectMetadata objectMetadata = new ObjectMetadata();
objectMetadata.setContentLength(bytes.length);
objectMetadata.setContentType(multipartFile.getContentType());
// 요청 바디 작성
PutObjectRequest putObjectRequest = new PutObjectRequest(this.bucket, getPath()+uuid, multipartFile.getInputStream(), objectMetadata)
.withCannedAcl(CannedAccessControlList.PublicRead);
// 업로드 요청
this.s3Client.putObject(putObjectRequest);
logger.info("upload complete! {}", putObjectRequest.getKey());
// DB에 파일 정보 저장 (저장 경로, 파일명, 저장 순서 등)
ProductFileDto productFileDto = new ProductFileDto(product_no, putObjectRequest.getKey(), originalName, uuid, idx);
list.add(productFileDto);
idx++;
}
return list;
}
}
ObjectMetadata
객체를 생성합니다. ObjectMetadata는 객체의 메타데이터 정보를 나타냅니다setContentLength()
로 파일의 바이트 배열 길이를 전달setContentType()
으로 파일 객체의 contentType을 전달PutObjectRequest
객체를 생성, 요청 바디를 작성합니다withCannedAcl()
메소드의 매개변수로 액세스 제어 정책을 전달합니다AmazonS3
의 putObject()
메소드에 요청 바디를 전달, 호출하면 업로드 요청이 완료됩니다DeleteObjectRequest
객체의 생성자에 bucket명, 삭제하고자 할 파일의 경로를 포함한 파일명을 전달해 객체를 생성합니다AmazonS3
의 deleteObject()
메소드에 요청 바디를 전달, 호출하면 삭제 요청이 완료됩니다