TIL(Today I Learned)

TIL - S3 Presigned URL을 통해 이미지 파일 업로드

Happy._. 2024. 8. 26. 22:24

build.gradle.kts에 의존성 추가

dependencies {
    implementation("com.amazonaws:aws-java-sdk-s3:1.12.741") // AWS S3
}

 

application.yml에 버킷명 및 AWS에서 발급받은 키 설정

aws:
  s3:
    bucket: <bucket-name>
    access-key: <access-key>
    secret-key: <secret-key>

 

S3Config 설정

@Configuration
class S3Config(
    @Value("\${aws.s3.access-key}") val accessKey: String,
    @Value("\${aws.s3.secret-key}") val secretKey: String
) {


    @Bean
    fun s3Client(): AmazonS3Client = AmazonS3ClientBuilder
        .standard()
        .withRegion(Regions.AP_NORTHEAST_2) // Seoul
        .withCredentials(
            AWSStaticCredentialsProvider(
                BasicAWSCredentials(accessKey, secretKey)
            )
        )
        .build() as AmazonS3Client
}
  • AmazonS3ClientBuilder.standard(): 표준 S3 클라이언트 빌더 사용
  • withRegion(): S3 클라이언트가 사용할 AWS 리전 설정
    • Regions.AP_NORTHEAST_2: 서울 리전
  • withCredentials(): 자격 증명 설정

 

Controller 설정

@RestController
class S3Controller(
    private val s3Service: S3Service
) {

    @GetMapping("/presigned-url")
    fun getPresignedUrl(
        @RequestParam filename: String,
    ): ResponseEntity<String> =
        ResponseEntity
            .status(HttpStatus.OK)
            .body(s3Service.getPresignedUrl(filename))
}
 
 
Service 설정
@Service
class S3Service(
    private val s3Client: AmazonS3Client,
    @Value("\${aws.s3.bucket}") val bucket: String
) {

    fun getPresignedUrl(filename: String): String =
        s3Client.generatePresignedUrl(
            GeneratePresignedUrlRequest(bucket, filename)
                .withMethod(HttpMethod.PUT)
                .withExpiration(
                    Date(System.currentTimeMillis() + EXPIRATION_TIME)
                )
        ).toString()


    companion object {
        const val EXPIRATION_TIME = 1000 * 60
    }
}
  • GeneratePresignedUrlRequest(bucket, filename): 버킷명과 파일명 사용해 Presigned URL 요청 생성
  • withMethod(HttpMethod.PUT): HTTP 메서드를 PUT으로 설정
  • withExpiration(Date(System.currentTimeMillis() + EXPIRATION_TIME)): URL의 만료 시간을 현재 시간으로부터 EXPIRATION_TIME 후로 설정
    • EXPIRATION_TIME: 1분

 

 

만료 시간이 지난 경우 다음과 같이 HTTP Status Code 403으로 응답