Skip to content

ss-keel-storage

ss-keel-storage provides a Storage implementation with a unified API across AWS S3, Google Cloud Storage (GCS), and local disk. Switch providers by changing config — your application code stays the same.

Implements: Storage

Terminal window
go get github.com/slice-soft/ss-keel-storage
import "github.com/slice-soft/ss-keel-storage"
storage, err := ssstorage.NewS3(ssstorage.S3Config{
Bucket: os.Getenv("S3_BUCKET"),
Region: os.Getenv("AWS_REGION"),
AccessKey: os.Getenv("AWS_ACCESS_KEY_ID"),
SecretKey: os.Getenv("AWS_SECRET_ACCESS_KEY"),
})
storage, err := ssstorage.NewGCS(ssstorage.GCSConfig{
Bucket: os.Getenv("GCS_BUCKET"),
CredentialsFile: os.Getenv("GOOGLE_APPLICATION_CREDENTIALS"),
})
storage, err := ssstorage.NewLocal(ssstorage.LocalConfig{
BaseDir: "./uploads",
BaseURL: "http://localhost:3000/uploads",
})

All providers share the same interface:

// Upload
file, _ := c.FormFile("avatar")
src, _ := file.Open()
defer src.Close()
err := storage.Put(ctx, "avatars/"+userID+".jpg", src, file.Size, "image/jpeg")
// Generate a signed URL (expires in 1 hour)
url, err := storage.URL(ctx, "avatars/"+userID+".jpg", time.Hour)
// Download
reader, err := storage.Get(ctx, "avatars/"+userID+".jpg")
defer reader.Close()
// Delete
err := storage.Delete(ctx, "avatars/"+userID+".jpg")
// File info
obj, err := storage.Stat(ctx, "avatars/"+userID+".jpg")
// obj.Size, obj.ContentType, obj.LastModified
func (c *AvatarController) upload(ctx *core.Ctx) error {
file, err := ctx.FormFile("avatar")
if err != nil {
return core.BadRequest("no file provided")
}
src, _ := file.Open()
defer src.Close()
key := fmt.Sprintf("avatars/%s.jpg", uuid.New())
if err := c.storage.Put(ctx.Context(), key, src, file.Size, file.Header.Get("Content-Type")); err != nil {
return core.Internal("upload failed", err)
}
url, _ := c.storage.URL(ctx.Context(), key, 365*24*time.Hour)
return ctx.Created(map[string]string{"url": url})
}