在 Kotlin 中使用 S3 和云存储
兼容 Amazon S3(Simple Storage Service)协议的云对象存储已成为存储非结构化数据(如图像、视频、日志、备份和构建产物)的事实标准。在 Kotlin 生态系统(JVM、Android、Kotlin Multiplatform)中,与 S3 交互主要有两种方式:官方的 AWS SDK for Java/Kotlin 和轻量级的 MinIO Java SDK。本文将详细介绍这两种方案,展示代码示例,并给出选择建议。
1. AWS SDK for Java (Kotlin)
Amazon 官方 SDK 支持 S3 的所有功能,包括多线程上传、生命周期管理、版本控制和加密。对于 Kotlin,只需在 build.gradle.kts 中添加依赖:
dependencies { implementation("software.amazon.awssdk:s3:2.27.0") implementation("software.amazon.awssdk:auth:2.27.0")}将文件上传到 S3 bucket 的基本示例:
import software.amazon.awssdk.auth.credentials.AwsBasicCredentialsimport software.amazon.awssdk.auth.credentials.StaticCredentialsProviderimport software.amazon.awssdk.regions.Regionimport software.amazon.awssdk.services.s3.S3Clientimport software.amazon.awssdk.services.s3.model.PutObjectRequestimport java.nio.file.Paths
fun main() { val credentials = AwsBasicCredentials.create("ACCESS_KEY", "SECRET_KEY") val s3 = S3Client.builder() .region(Region.EU_CENTRAL_1) .credentialsProvider(StaticCredentialsProvider.create(credentials)) .build()
val request = PutObjectRequest.builder() .bucket("my-bucket") .key("uploads/photo.jpg") .contentType("image/jpeg") .build()
s3.putObject(request, Paths.get("/local/path/photo.jpg")) println("文件已上传")}下载对象:
import software.amazon.awssdk.services.s3.model.GetObjectRequest
val getRequest = GetObjectRequest.builder() .bucket("my-bucket") .key("uploads/photo.jpg") .build()
s3.getObject(getRequest, Paths.get("/local/download/photo.jpg"))2. MinIO Java SDK(S3 兼容存储)
MinIO 是一个高性能的开源对象存储,完全兼容 S3 API。其 SDK 既可用于本地 MinIO,也可用于 AWS S3、DigitalOcean Spaces、Yandex Object Storage 等其他提供商。添加依赖:
dependencies { implementation("io.minio:minio:8.5.10")}通过 MinIO SDK 上传文件的示例:
import io.minio.MinioClientimport io.minio.PutObjectArgsimport java.io.FileInputStream
fun main() { val minioClient = MinioClient.builder() .endpoint("https://play.min.io") .credentials("minioadmin", "minioadmin") .build()
val inputStream = FileInputStream("/local/data/report.pdf") minioClient.putObject( PutObjectArgs.builder() .bucket("documents") .`object`("reports/2024/report.pdf") .stream(inputStream, inputStream.available(), -1) .contentType("application/pdf") .build() ) println("文件已上传到 MinIO")}通过 MinIO 下载:
import io.minio.GetObjectArgsimport java.io.FileOutputStream
val getArgs = GetObjectArgs.builder() .bucket("documents") .`object`("reports/2024/report.pdf") .build()
val response = minioClient.getObject(getArgs)response.use { stream -> FileOutputStream("/local/download/report.pdf").use { output -> stream.transferTo(output) }}3. 使用公共链接和有效期
生成用于下载的临时链接(presigned URL),无需