A wrapper for working with files in popular cloud storage
- Direct links (
bypass
) - Local (
local
) - S3 (
s3
) - Cloudfront (
cloudfront
) - Yandex Object Storage (
yos
)
Types values:
- TypeBypass = "bypass"
- TypeLocal = "local"
- TypeS3 = "s3"
- TypeCloudFront = "cf"
- TypeCloudFrontSigned = "cfs"
- TypeYOS = "yos"
Each of the types implements the interface:
Storage interface {
Store(filePath, path string) (cLink string, err error)
GetURL(cLink string, options ...interface{}) (URL string)
Remove(cLink string) (err error)
GetCLink(path string) (cLink string)
StoreByCLink(filePath, cLink string) (err error)
}
You can create and use each of the types of storages separately.
Example:
import "github.com/rosberry/storage/local"
lStorage := local.New(&local.Config{
StorageKey: cfg["storageKey"],
Endpoint: cfg["endpoint"],
Root: cfg["root"],
BufferSize: 32 * 1024,
})
cLink, err := lStorage.Store(filePath, path)
...
url := lStorage.GetURL(cLink)
...
import "github.com/rosberry/storage/bypass"
bpStorage := bypass.New()
import "github.com/rosberry/storage/local"
lStorage := local.New(&local.Config{
StorageKey: cfg["storageKey"],
Endpoint: cfg["endpoint"],
Root: cfg["root"],
BufferSize: 32 * 1024,
})
import "github.com/rosberry/storage/s3"
s3Storage := s3.New(&s3.Config{
StorageKey: cfg["storage_key"],
Region: cfg["region"],
AccessKeyID: cfg["access_key_id"],
SecretAccessKey: cfg["secret_access_key"],
BucketName: cfg["bucket_name"],
Prefix: cfg["prefix"],
})
import "github.com/rosberry/storage/cloudfront"
cfStorage := cloudfront.New(&cloudfront.Config{
StorageKey: cfg["storage_key"],
DomainName: cfg["domain_name"],
CFPrefix: cfg["cf_prefix"],
StorageCtl: s3Storage, // see section S3
})
// with signed url's
cfStorage := cloudfront.New(&cloudfront.Config{
StorageKey: cfg["storage_key"],
DomainName: cfg["domain_name"],
CFPrefix: cfg["cf_prefix"],
SignURLs: true,
PrivateKeyID: cfg["private_key_id"],
PrivateKey: cfg["private_key"],
StorageCtl: s3Storage,
})
import "github.com/rosberry/storage/yos/v2"
yosStorage := yos.New(&yos.Config{
StorageKey: cfg["storage_key"],
Region: cfg["region"],
AccessKeyID: cfg["access_key_id"],
SecretAccessKey: cfg["secret_access_key"],
BucketName: cfg["bucket_name"],
Prefix: cfg["prefix"],
})
But the correct use of the library - use of an abstract storage, which includes one or more implementations of storage types. You do not have to use specific types of methods. Use abstract storage methods.
import (
"github.com/rosberry/storage"
"github.com/rosberry/storage/bypass"
"github.com/rosberry/storage/local"
"github.com/rosberry/storage/s3"
"github.com/rosberry/storage/yos/v2"
"github.com/rosberry/storage/cloudfront"
)
// Init storage types
// ....
// Add storage types
// bypass
storage.AddStorage("http", bypass.New())
storage.AddStorage("https", bypass.New())
// local
storage.AddStorage(localStorageKey, lStorage)
// s3
storage.AddStorage(s3StorageKey, s3Storage)
// yos
storage.AddStorage(yosStoragKey, yosStorage)
// cloudfront
storage.AddStorage(cfStorageKey, cfStorage)
storage.AddStorage(cfsStorageKey, cfsStorage)
// usage
cLink, err := storage.CreateCLinkInStorage(filePath, path, s3StorageKey)
...
url := storage.GetURL(cLink)
...
You can create an unlimited number of the local instances of the abstract storage and use the same methods.
// ...
import "github.com/rosberry/storage/core"
localInstance := core.New()
// Init storage types
// ....
// Add storage types
// bypass
localInstance.AddStorage("http", bypass.New())
localInstance.AddStorage("https", bypass.New())
// local
localInstance.AddStorage(localStorageKey, lStorage)
// ...
// usage
cLink, err := localInstance.CreateCLinkInStorage(filePath, path, s3StorageKey)
...
url := localInstance.GetURL(cLink)
...
You can also use instance creation with automatic configuration parsing
// ...
import "github.com/rosberry/storage/core"
//...
var config *core.StoragesConfig
// Parsing config from file
//...
localInstance := storage.NewWithConfig(&config)
// usage
cLink, err := localInstance.CreateCLinkInStorage(filePath, path, s3StorageKey)
...
url := localInstance.GetURL(cLink)
...
The configuration is the type:
// package github.com/rosberry/storage/core
type (
StoragesConfig struct {
Default string `json:"default" yaml:"default"`
Instances []StorageConfig `json:"instances" yaml:"instances"`
}
StorageConfig struct {
Key string `json:"key" yaml:"key"`
Type string `json:"type" yaml:"type"`
Cfg map[string]string `json:"config" yaml:"config"`
}
)
Add storage to storage list
func AddStorage(storageKey string, storage Storage) (err error)
Get storage from storage list
func GetStorage(storageKey string) (s Storage, err error)
Save file to storage and create storage link
//default storage
func CreateCLink(filePath, path string) (cLink string, err error)
//selected storage
func CreateCLinkInStorage(filePath, path, storageKey string) (cLink string, err error)
Return http link storage link
func GetURL(cLink string, options ...interface{}) (URL string)
Delete file in storage
func Delete(cLink string) (err error)
Set storage as default
func SetDefaultStorage(storageKey string) (err error)
You can create cLink without upload file and then upload file later.
Prepare cLink (by analogy with the CreateCLink...
):
//default storage
func PrepareCLinkInStorage(path, storageKey string) (cLink string, err error)
//selected storage
func PrepareCLink(path string) (cLink string, err error)
Upload file:
func UploadByCLink(filePath, cLink string) (err error)
if sp.Photo != "" {
tmpfile, _ := ioutil.TempFile("", "avatar-*.jpg")
tmpPath := tmpfile.Name()
tmpfile.Close()
defer os.Remove(tmpPath)
err := downloadFile(tmpPath, sp.Photo)
if err != nil {
log.Println(err)
}
link, err := storage.CreateCLinkInStorage(tmpPath, fmt.Sprintf("users/%v", user.ID), "yos")
if err != nil {
log.Printf("Failed download user avatar for user %v\n", u.ID)
user.Photo = sp.Photo
} else {
user.Photo = link
}
}
- You can not use the '_' symbol in the key
- The key must be in the lower case
// Glossary // path - The name with which the user wants to save the file // internalPath - The path to the file in the repository (includes the prefix) // cLink - Formed as a storage key + ':' + path
This project is owned and maintained by Rosberry. We build mobile apps for users worldwide ๐.
Check out our open source projects, read our blog or give us a high-five on ๐ฆ @rosberryapps.
This project is available under the MIT license. See the LICENSE file for more info.