|
|
@ -6,6 +6,7 @@ package storage
|
|
|
|
import (
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"context"
|
|
|
|
"crypto/tls"
|
|
|
|
"crypto/tls"
|
|
|
|
|
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"io"
|
|
|
|
"net/http"
|
|
|
|
"net/http"
|
|
|
|
"net/url"
|
|
|
|
"net/url"
|
|
|
@ -52,10 +53,12 @@ type MinioStorageConfig struct {
|
|
|
|
BasePath string `ini:"MINIO_BASE_PATH"`
|
|
|
|
BasePath string `ini:"MINIO_BASE_PATH"`
|
|
|
|
UseSSL bool `ini:"MINIO_USE_SSL"`
|
|
|
|
UseSSL bool `ini:"MINIO_USE_SSL"`
|
|
|
|
InsecureSkipVerify bool `ini:"MINIO_INSECURE_SKIP_VERIFY"`
|
|
|
|
InsecureSkipVerify bool `ini:"MINIO_INSECURE_SKIP_VERIFY"`
|
|
|
|
|
|
|
|
ChecksumAlgorithm string `ini:"MINIO_CHECKSUM_ALGORITHM"`
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// MinioStorage returns a minio bucket storage
|
|
|
|
// MinioStorage returns a minio bucket storage
|
|
|
|
type MinioStorage struct {
|
|
|
|
type MinioStorage struct {
|
|
|
|
|
|
|
|
cfg *MinioStorageConfig
|
|
|
|
ctx context.Context
|
|
|
|
ctx context.Context
|
|
|
|
client *minio.Client
|
|
|
|
client *minio.Client
|
|
|
|
bucket string
|
|
|
|
bucket string
|
|
|
@ -90,6 +93,10 @@ func NewMinioStorage(ctx context.Context, cfg interface{}) (ObjectStorage, error
|
|
|
|
}
|
|
|
|
}
|
|
|
|
config := configInterface.(MinioStorageConfig)
|
|
|
|
config := configInterface.(MinioStorageConfig)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if config.ChecksumAlgorithm != "" && config.ChecksumAlgorithm != "default" && config.ChecksumAlgorithm != "md5" {
|
|
|
|
|
|
|
|
return nil, fmt.Errorf("invalid minio checksum algorithm: %s", config.ChecksumAlgorithm)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
log.Info("Creating Minio storage at %s:%s with base path %s", config.Endpoint, config.Bucket, config.BasePath)
|
|
|
|
log.Info("Creating Minio storage at %s:%s with base path %s", config.Endpoint, config.Bucket, config.BasePath)
|
|
|
|
|
|
|
|
|
|
|
|
minioClient, err := minio.New(config.Endpoint, &minio.Options{
|
|
|
|
minioClient, err := minio.New(config.Endpoint, &minio.Options{
|
|
|
@ -112,6 +119,7 @@ func NewMinioStorage(ctx context.Context, cfg interface{}) (ObjectStorage, error
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return &MinioStorage{
|
|
|
|
return &MinioStorage{
|
|
|
|
|
|
|
|
cfg: &config,
|
|
|
|
ctx: ctx,
|
|
|
|
ctx: ctx,
|
|
|
|
client: minioClient,
|
|
|
|
client: minioClient,
|
|
|
|
bucket: config.Bucket,
|
|
|
|
bucket: config.Bucket,
|
|
|
@ -123,7 +131,7 @@ func (m *MinioStorage) buildMinioPath(p string) string {
|
|
|
|
return strings.TrimPrefix(path.Join(m.basePath, path.Clean("/" + strings.ReplaceAll(p, "\\", "/"))[1:]), "/")
|
|
|
|
return strings.TrimPrefix(path.Join(m.basePath, path.Clean("/" + strings.ReplaceAll(p, "\\", "/"))[1:]), "/")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Open open a file
|
|
|
|
// Open opens a file
|
|
|
|
func (m *MinioStorage) Open(path string) (Object, error) {
|
|
|
|
func (m *MinioStorage) Open(path string) (Object, error) {
|
|
|
|
opts := minio.GetObjectOptions{}
|
|
|
|
opts := minio.GetObjectOptions{}
|
|
|
|
object, err := m.client.GetObject(m.ctx, m.bucket, m.buildMinioPath(path), opts)
|
|
|
|
object, err := m.client.GetObject(m.ctx, m.bucket, m.buildMinioPath(path), opts)
|
|
|
@ -133,7 +141,7 @@ func (m *MinioStorage) Open(path string) (Object, error) {
|
|
|
|
return &minioObject{object}, nil
|
|
|
|
return &minioObject{object}, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Save save a file to minio
|
|
|
|
// Save saves a file to minio
|
|
|
|
func (m *MinioStorage) Save(path string, r io.Reader, size int64) (int64, error) {
|
|
|
|
func (m *MinioStorage) Save(path string, r io.Reader, size int64) (int64, error) {
|
|
|
|
uploadInfo, err := m.client.PutObject(
|
|
|
|
uploadInfo, err := m.client.PutObject(
|
|
|
|
m.ctx,
|
|
|
|
m.ctx,
|
|
|
@ -141,7 +149,14 @@ func (m *MinioStorage) Save(path string, r io.Reader, size int64) (int64, error)
|
|
|
|
m.buildMinioPath(path),
|
|
|
|
m.buildMinioPath(path),
|
|
|
|
r,
|
|
|
|
r,
|
|
|
|
size,
|
|
|
|
size,
|
|
|
|
minio.PutObjectOptions{ContentType: "application/octet-stream"},
|
|
|
|
minio.PutObjectOptions{
|
|
|
|
|
|
|
|
ContentType: "application/octet-stream",
|
|
|
|
|
|
|
|
// some storages like:
|
|
|
|
|
|
|
|
// * https://developers.cloudflare.com/r2/api/s3/api/
|
|
|
|
|
|
|
|
// * https://www.backblaze.com/b2/docs/s3_compatible_api.html
|
|
|
|
|
|
|
|
// do not support "x-amz-checksum-algorithm" header, so use legacy MD5 checksum
|
|
|
|
|
|
|
|
SendContentMd5: m.cfg.ChecksumAlgorithm == "md5",
|
|
|
|
|
|
|
|
},
|
|
|
|
)
|
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
|
return 0, convertMinioErr(err)
|
|
|
|
return 0, convertMinioErr(err)
|
|
|
|