72 lines
2.5 KiB
Kotlin
72 lines
2.5 KiB
Kotlin
package me.wypark.blogbackend.domain.image
|
|
|
|
import org.springframework.beans.factory.annotation.Value
|
|
import org.springframework.stereotype.Service
|
|
import org.springframework.web.multipart.MultipartFile
|
|
import software.amazon.awssdk.core.sync.RequestBody
|
|
import software.amazon.awssdk.services.s3.S3Client
|
|
import software.amazon.awssdk.services.s3.model.GetUrlRequest
|
|
import software.amazon.awssdk.services.s3.model.PutObjectRequest
|
|
import java.util.*
|
|
|
|
@Service
|
|
class ImageService(
|
|
private val s3Client: S3Client,
|
|
@Value("\${spring.cloud.aws.s3.endpoint:http://minio:9000}") private val endpoint: String
|
|
) {
|
|
private val bucketName = "blog-images" // 버킷 이름
|
|
|
|
init {
|
|
createBucketIfNotExists()
|
|
}
|
|
|
|
fun uploadImage(file: MultipartFile): String {
|
|
// 1. 파일명 중복 방지 (UUID 사용)
|
|
val originalName = file.originalFilename ?: "image.jpg"
|
|
val ext = originalName.substringAfterLast(".", "jpg")
|
|
val fileName = "${UUID.randomUUID()}.$ext"
|
|
|
|
// 2. S3(MinIO)로 업로드
|
|
val putObjectRequest = PutObjectRequest.builder()
|
|
.bucket(bucketName)
|
|
.key(fileName)
|
|
.contentType(file.contentType)
|
|
.build()
|
|
|
|
s3Client.putObject(putObjectRequest, RequestBody.fromInputStream(file.inputStream, file.size))
|
|
|
|
// 3. 접속 가능한 URL 반환
|
|
// 로컬 개발 환경에서는 localhost 주소를 직접 조합해서 줍니다.
|
|
// 배포 시에는 실제 도메인이나 CloudFront 주소로 변경해야 합니다.
|
|
return "$endpoint/$bucketName/$fileName"
|
|
}
|
|
|
|
private fun createBucketIfNotExists() {
|
|
try {
|
|
// 버킷 존재 여부 확인 (없으면 에러 발생하므로 try-catch)
|
|
s3Client.headBucket { it.bucket(bucketName) }
|
|
} catch (e: Exception) {
|
|
// 버킷 생성
|
|
s3Client.createBucket { it.bucket(bucketName) }
|
|
|
|
// ⭐ 버킷을 Public(공개)으로 설정 (이미지 조회를 위해 필수)
|
|
val policy = """
|
|
{
|
|
"Version": "2012-10-17",
|
|
"Statement": [
|
|
{
|
|
"Effect": "Allow",
|
|
"Principal": { "AWS": ["*"] },
|
|
"Action": ["s3:GetObject"],
|
|
"Resource": ["arn:aws:s3:::$bucketName/*"]
|
|
}
|
|
]
|
|
}
|
|
""".trimIndent()
|
|
|
|
s3Client.putBucketPolicy {
|
|
it.bucket(bucketName).policy(policy)
|
|
}
|
|
}
|
|
}
|
|
} |