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