Skip to main content

AWS SDK for Go (v2)

The AWS SDK for Go v2 is the modern, idiomatic Go SDK from AWS. It works against Filebase via BaseEndpoint and Region: "auto".

Install​

go get github.com/aws/aws-sdk-go-v2
go get github.com/aws/aws-sdk-go-v2/credentials
go get github.com/aws/aws-sdk-go-v2/service/s3
go get github.com/aws/aws-sdk-go-v2/feature/s3/manager

Initialize the client​

filebase.go
package filebase

import (
"context"
"os"

"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/credentials"
"github.com/aws/aws-sdk-go-v2/service/s3"
)

func New() *s3.Client {
creds := credentials.NewStaticCredentialsProvider(
os.Getenv("FILEBASE_KEY"),
os.Getenv("FILEBASE_SECRET"),
"",
)

return s3.New(s3.Options{
BaseEndpoint: aws.String("https://s3.filebase.io"),
Region: "auto",
Credentials: creds,
})
}

List buckets​

ctx := context.Background()
client := filebase.New()

out, _ := client.ListBuckets(ctx, &s3.ListBucketsInput{})
for _, b := range out.Buckets {
fmt.Println(*b.Name)
}

Create a bucket​

import "github.com/aws/aws-sdk-go-v2/service/s3/types"

_, _ = client.CreateBucket(ctx, &s3.CreateBucketInput{
Bucket: aws.String("my-bucket"),
})

// Public bucket
_, _ = client.CreateBucket(ctx, &s3.CreateBucketInput{
Bucket: aws.String("my-public-bucket"),
ACL: types.BucketCannedACLPublicRead,
})

Upload an object​

f, _ := os.Open("photo.jpg")
defer f.Close()

_, _ = client.PutObject(ctx, &s3.PutObjectInput{
Bucket: aws.String("my-bucket"),
Key: aws.String("photo.jpg"),
Body: f,
ContentType: aws.String("image/jpeg"),
CacheControl: aws.String("public, max-age=31536000"),
})

For large files, use the upload manager:

import "github.com/aws/aws-sdk-go-v2/feature/s3/manager"

uploader := manager.NewUploader(client, func(u *manager.Uploader) {
u.PartSize = 8 * 1024 * 1024 // 8 MB
u.Concurrency = 4
})

f, _ := os.Open("./video.mp4")
defer f.Close()

_, err := uploader.Upload(ctx, &s3.PutObjectInput{
Bucket: aws.String("my-bucket"),
Key: aws.String("video.mp4"),
Body: f,
})

List objects​

paginator := s3.NewListObjectsV2Paginator(client, &s3.ListObjectsV2Input{
Bucket: aws.String("my-bucket"),
Prefix: aws.String("photos/"),
})

for paginator.HasMorePages() {
page, err := paginator.NextPage(ctx)
if err != nil {
log.Fatal(err)
}
for _, obj := range page.Contents {
fmt.Println(*obj.Key, obj.Size)
}
}

Download an object​

out, _ := client.GetObject(ctx, &s3.GetObjectInput{
Bucket: aws.String("my-bucket"),
Key: aws.String("photo.jpg"),
})
defer out.Body.Close()

f, _ := os.Create("downloaded.jpg")
defer f.Close()

io.Copy(f, out.Body)

For very large objects, use the download manager:

downloader := manager.NewDownloader(client)

f, _ := os.Create("./downloaded.bin")
defer f.Close()

_, _ = downloader.Download(ctx, f, &s3.GetObjectInput{
Bucket: aws.String("my-bucket"),
Key: aws.String("large-file.bin"),
})

Delete an object​

_, _ = client.DeleteObject(ctx, &s3.DeleteObjectInput{
Bucket: aws.String("my-bucket"),
Key: aws.String("photo.jpg"),
})

Pre-signed URLs​

import "time"

presigner := s3.NewPresignClient(client)

// Read URL
req, _ := presigner.PresignGetObject(ctx,
&s3.GetObjectInput{
Bucket: aws.String("my-bucket"),
Key: aws.String("private.pdf"),
},
s3.WithPresignExpires(time.Hour),
)

fmt.Println(req.URL)

// Write URL
req, _ = presigner.PresignPutObject(ctx,
&s3.PutObjectInput{
Bucket: aws.String("uploads"),
Key: aws.String("user/photo.jpg"),
ContentType: aws.String("image/jpeg"),
},
s3.WithPresignExpires(10*time.Minute),
)

Error handling​

import "github.com/aws/smithy-go"

_, err := client.GetObject(ctx, &s3.GetObjectInput{Bucket: ..., Key: ...})
if err != nil {
var ae smithy.APIError
if errors.As(err, &ae) {
switch ae.ErrorCode() {
case "NoSuchKey":
// handle missing key
case "NoSuchBucket":
// handle missing bucket
default:
return fmt.Errorf("s3 error: %s: %s", ae.ErrorCode(), ae.ErrorMessage())
}
}
return err
}

What's next​