Working with S3 and Cloud Storage in Kotlin
Cloud object storage compatible with the Amazon S3 (Simple Storage Service) protocol has become the de facto standard for storing unstructured data: images, videos, logs, backups, and build artifacts. In the Kotlin ecosystem (JVM, Android, Kotlin Multiplatform), two main approaches are used for interacting with S3: the official AWS SDK for Java/Kotlin and the lightweight MinIO Java SDK. In this article, we will cover both options, show code examples, and provide recommendations for choosing between them.
1. AWS SDK for Java (Kotlin)
The official SDK from Amazon supports all S3 features, including multipart upload, lifecycle management, versioning, and encryption. For Kotlin, simply add the dependency in build.gradle.kts:
dependencies { implementation("software.amazon.awssdk:s3:2.27.0") implementation("software.amazon.awssdk:auth:2.27.0")}Basic example of uploading a file to an 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("File uploaded")}Downloading an object:
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-Compatible Storage)
MinIO is a high-performance, open-source object storage fully compatible with the S3 API. Its SDK is suitable for working with local MinIO as well as AWS S3, DigitalOcean Spaces, Yandex Object Storage, and other providers. Add the dependency:
dependencies { implementation("io.minio:minio:8.5.10")}Example of uploading a file via the 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("File uploaded to MinIO")}Downloading via 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. Working with Public Links and Expiration
Generating a temporary link (presigned URL) for downloading without a