Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
126 changes: 126 additions & 0 deletions src/content/docs/r2/examples/aws/aws-sdk-kotlin.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
---
title: aws-sdk-kotlin
pcx_content_type: example
---

import { Render } from "~/components";

<Render file="keys" product="r2" />
<br />

This example uses the [aws-sdk-kotlin](https://github.com/aws/aws-sdk-kotlin). You must pass in the R2 configuration credentials when instantiating your `S3` client:

## Basic Usage

```kotlin
import aws.sdk.kotlin.runtime.auth.credentials.StaticCredentialsProvider
import aws.sdk.kotlin.services.s3.S3Client
import aws.sdk.kotlin.services.s3.model.ListObjectsV2Request
import aws.smithy.kotlin.runtime.auth.awscredentials.Credentials
import aws.smithy.kotlin.runtime.net.url.Url
import kotlinx.coroutines.runBlocking

val ACCOUNT_ID = "<ACCOUNT_ID>"
val ACCESS_KEY_ID = "<ACCESS_KEY_ID>"
val SECRET_ACCESS_KEY = "<SECRET_ACCESS_KEY>"

fun main() = runBlocking {
S3Client.fromEnvironment {
region = "auto" // Required by SDK, but not used by R2
endpointUrl = Url.parse("https://${ACCOUNT_ID}.r2.cloudflarestorage.com")
credentialsProvider = StaticCredentialsProvider(
Credentials(
accessKeyId = ACCESS_KEY_ID,
secretAccessKey = SECRET_ACCESS_KEY
),
)
}.use { r2Client ->
println("Available buckets:")
r2Client.listBuckets().buckets?.forEach { bucket ->
println("* ${bucket.name}")
}

val bucketName = "<BUCKET_NAME>"
println("\nObjects in bucket '${bucketName}':")
r2Client.listObjectsV2(ListObjectsV2Request { bucket = bucketName }).contents?.forEach {
println("* ${it.key} (size: ${it.size} bytes, modified: ${it.lastModified})")
}
}
}
```

```sh output
Available buckets:
* my-bucket-1
* my-bucket-2

Objects in bucket 'my-bucket-1':
* image1.png (size: 253167 bytes, modified: 2026-01-17T11:30:58.896Z)
* image2.png (size: 247027 bytes, modified: 2026-01-17T11:30:57.779Z)
```

## Generate presigned URLs

You can also generate presigned links that can be used to temporarily share public read or write access to a bucket.

```kotlin
import aws.sdk.kotlin.runtime.auth.credentials.StaticCredentialsProvider
import aws.sdk.kotlin.services.s3.S3Client
import aws.sdk.kotlin.services.s3.model.GetObjectRequest
import aws.sdk.kotlin.services.s3.model.PutObjectRequest
import aws.sdk.kotlin.services.s3.presigners.presignGetObject
import aws.sdk.kotlin.services.s3.presigners.presignPutObject
import aws.smithy.kotlin.runtime.auth.awscredentials.Credentials
import aws.smithy.kotlin.runtime.net.url.Url
import kotlinx.coroutines.runBlocking
import kotlin.time.Duration.Companion.minutes

val ACCOUNT_ID = "<ACCOUNT_ID>"
val ACCESS_KEY_ID = "<ACCESS_KEY_ID>"
val SECRET_ACCESS_KEY = "<SECRET_ACCESS_KEY>"

fun main() = runBlocking {
S3Client.fromEnvironment {
region = "auto" // Required by SDK, but not used by R2
endpointUrl = Url.parse("https://${ACCOUNT_ID}.r2.cloudflarestorage.com")
credentialsProvider = StaticCredentialsProvider(
Credentials(
accessKeyId = ACCESS_KEY_ID,
secretAccessKey = SECRET_ACCESS_KEY
),
)
}.use { r2Client ->
val bucketName = "<BUCKET_NAME>"

val uploadUrl = r2Client.presignPutObject(
input = PutObjectRequest {
bucket = bucketName
key = "README.md"
},
duration = 15.minutes,
).url
println(uploadUrl)

val getUrl = r2Client.presignGetObject(
input = GetObjectRequest {
bucket = bucketName
key = "README.md"
},
duration = 15.minutes,
).url
println(getUrl)
}
}
```

You can use these presigned URLs with any HTTP client. For example, to upload a file using the PUT URL:

```bash
curl -X PUT "https://<your-presigned-put-url>" -H "Content-Type: application/octet-stream" --data-binary "@local-file.txt"
```

To download a file using the GET URL:

```bash
curl -X GET "https://<your-presigned-get-url>" -o downloaded-file.txt
```