사실 이전에도 똑같은 주제로 글을 올린 적이 있었는데
io.awspring.cloud:spring-cloud-aws-s3:2.xx 버전에서
io.awspring.cloud:spring-cloud-aws-s3:3.xx 에서 코드가 바뀐 부분이 있어 다시 올리게 되었다.
※ 이 글은 S3 bucket 까지 설정했다는 가정 하에 쓴 글입니다.
//aws s3 연동
implementation 'io.awspring.cloud:spring-cloud-aws-s3:3.0.2'
dependencies에 추가해주면 된다.
spring:
cloud:
aws:
credentials:
accessKey: <YOUR_ACCESS_KEY>
secretKey: <YOUR_SECRET_KEY>
s3:
bucket: <BUCKET_NAME>
region:
static: <REGION>
stack:
auto: false
accessKey, secretKey, bucketName, region 을 입력해주면 된다.
🚨🚨🚨 주의사항 🚨🚨🚨
Github 업로드 시 절대 public 한 repository에 올리면 안된다.
.gitignore에 application.yml을 추가하고 업로드를 하여 accessKey secretKey 가 노출되지 않도록 해야 한다.
S3Client에 accessKey, bucketName, region을 주입시켜야 한다.
@Configuration
public class AWSConfig {
@Value("${spring.cloud.aws.credentials.accessKey}")
private String accessKey;
@Value("${spring.cloud.aws.credentials.secretKey}")
private String accessSecret;
@Value("${spring.cloud.aws.region.static}")
private String region;
@Bean
public S3Client s3Client() {
return S3Client.builder()
.credentialsProvider(this::awsCredentials)
.region(Region.of(region))
.build();
}
private AwsCredentials awsCredentials() {
return new AwsCredentials() {
@Override
public String accessKeyId() {
return accessKey;
}
@Override
public String secretAccessKey() {
return accessSecret;
}
};
}
}
파일 이름을 설정해주는 클래스이다.
public class CommonUtils {
public static final String FILE_EXTENSION_SEPARATOR = ".";
public static String getFileName(String originalFileName) {
int fileExtensionIndex = originalFileName.lastIndexOf(FILE_EXTENSION_SEPARATOR);
return originalFileName.substring(0, fileExtensionIndex); //파일 이름
}
public static String buildFileName(String originalFileName) {
int fileExtensionIndex = originalFileName.lastIndexOf(FILE_EXTENSION_SEPARATOR); //파일 확장자 구분선
String fileExtension = originalFileName.substring(fileExtensionIndex); //파일 확장자
String fileName = originalFileName.substring(0, fileExtensionIndex); //파일 이름
String now = String.valueOf(System.currentTimeMillis()); //파일 업로드 시간
return fileName + "_" + now + fileExtension;
}
}
@Slf4j
@RequiredArgsConstructor
@Component
public class AwsS3Service {
private final S3Client s3Client;
@Value("${spring.cloud.aws.s3.bucket}")
private String bucketName;
public String uploadFile(MultipartFile multipartFile) {
if(multipartFile.isEmpty()) {
log.info("image is null");
return "";
}
String fileName = getFileName(multipartFile);
try {
PutObjectRequest putObjectRequest = PutObjectRequest.builder()
.bucket(bucketName)
.contentType(multipartFile.getContentType())
.contentLength(multipartFile.getSize())
.key(fileName)
.build();
RequestBody requestBody = RequestBody.fromBytes(multipartFile.getBytes());
s3Client.putObject(putObjectRequest, requestBody);
} catch (IOException e) {
log.error("cannot upload image",e);
throw new RuntimeException(e);
}
GetUrlRequest getUrlRequest = GetUrlRequest.builder()
.bucket(bucketName)
.key(fileName)
.build();
return s3Client.utilities().getUrl(getUrlRequest).toString();
}
public String getFileName(MultipartFile multipartFile) {
if(multipartFile.isEmpty()) return "";
return CommonUtils.buildFileName(multipartFile.getOriginalFilename());
}
}
Postman으로 테스트한 결과 성공적으로 업로드 된 것을 볼 수 있었다.
