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
}