feat(api): docs & folders basid curd implemention
This commit is contained in:
@@ -1,26 +1,26 @@
|
||||
package storage
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/cast"
|
||||
)
|
||||
|
||||
type ObjectStorage interface {
|
||||
// 获取上传对象预签名URL
|
||||
PresignedPutObject(ctx context.Context, objectName string, expires time.Duration) (u *url.URL, err error)
|
||||
// 获取访问对象预签名URL
|
||||
PresignedGetObject(ctx context.Context, objectName string, expires time.Duration) (u *url.URL, err error)
|
||||
// 移动对象
|
||||
MoveObject(ctx context.Context, src, dst string) error
|
||||
// 检查文件是否存在
|
||||
ObjectExists(ctx context.Context, objectName string) (bool, error)
|
||||
}
|
||||
// type ObjectStorage interface {
|
||||
// // 获取上传对象预签名URL
|
||||
// PresignedPutObject(ctx context.Context, objectName string, expires time.Duration) (u *url.URL, err error)
|
||||
// // 获取访问对象预签名URL
|
||||
// PresignedGetObject(ctx context.Context, objectName string, expires time.Duration) (u *url.URL, err error)
|
||||
// // 移动对象
|
||||
// MoveObject(ctx context.Context, src, dst string) error
|
||||
// // 检查文件是否存在
|
||||
// ObjectExists(ctx context.Context, objectName string) (bool, error)
|
||||
// // 获取对象创建时间
|
||||
// GetObjectCreatedTime(ctx context.Context, objectName string) (time.Time, error)
|
||||
// }
|
||||
|
||||
func NewObjectStorage(dsn string) (ObjectStorage, error) {
|
||||
func NewObjectStorage(dsn string) (*StorageMinio, error) {
|
||||
u, err := url.Parse(dsn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -30,9 +30,9 @@ func NewObjectStorage(dsn string) (ObjectStorage, error) {
|
||||
pass, _ := u.User.Password()
|
||||
|
||||
switch u.Scheme {
|
||||
case "cos":
|
||||
// ex: cos://examplebucket-1250000000.cos.COS_REGION.myqcloud.com
|
||||
return newCosStorage(u.Host, user, pass)
|
||||
// case "cos":
|
||||
// ex: cos://examplebucket-1250000000.cos.COS_REGION.myqcloud.com
|
||||
// return newCosStorage(u.Host, user, pass)
|
||||
case "minio":
|
||||
// ex: minio://minio-api:9001?secure=false&bucket=images
|
||||
secure := cast.ToBool(u.Query().Get("secure"))
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
package storage
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/tencentyun/cos-go-sdk-v5"
|
||||
)
|
||||
|
||||
var _ ObjectStorage = (*storageCos)(nil)
|
||||
|
||||
type storageCos struct {
|
||||
client *cos.Client
|
||||
|
||||
host string
|
||||
accessKey string
|
||||
accessSecret string
|
||||
bucket string
|
||||
}
|
||||
|
||||
func newCosStorage(host, accessKey, accessSecret string) (ObjectStorage, error) {
|
||||
parts := strings.Split(host, ".")
|
||||
if len(parts) != 5 {
|
||||
return nil, errors.New("invalid cos host")
|
||||
}
|
||||
parts = strings.Split(parts[0], "-")
|
||||
if len(parts) != 2 {
|
||||
return nil, errors.New("invalid cos host")
|
||||
}
|
||||
bucketName := parts[0]
|
||||
|
||||
u, err := url.Parse("https://" + host)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
client := cos.NewClient(&cos.BaseURL{BucketURL: u}, &http.Client{
|
||||
Transport: &cos.AuthorizationTransport{
|
||||
SecretID: accessKey,
|
||||
SecretKey: accessSecret,
|
||||
},
|
||||
})
|
||||
return &storageCos{
|
||||
client: client,
|
||||
host: host,
|
||||
accessKey: accessKey,
|
||||
accessSecret: accessSecret,
|
||||
bucket: bucketName,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// PresignedPutObject implements ObjectStorage
|
||||
func (c *storageCos) PresignedPutObject(ctx context.Context, objectName string, expires time.Duration) (u *url.URL, err error) {
|
||||
return c.client.Object.GetPresignedURL(ctx, "PUT", objectName, c.accessKey, c.accessSecret, expires, nil)
|
||||
}
|
||||
|
||||
// PresignedGetObject implements ObjectStorage
|
||||
func (c *storageCos) PresignedGetObject(ctx context.Context, objectName string, expires time.Duration) (u *url.URL, err error) {
|
||||
return c.client.Object.GetPresignedURL(ctx, "GET", objectName, c.accessKey, c.accessSecret, expires, nil)
|
||||
}
|
||||
|
||||
// MoveObject implements ObjectStorage
|
||||
func (c *storageCos) MoveObject(ctx context.Context, src string, dst string) error {
|
||||
srcURL := fmt.Sprintf("%s/%s", c.host, src)
|
||||
|
||||
if _, _, err := c.client.Object.Copy(ctx, dst, srcURL, nil); err != nil {
|
||||
return fmt.Errorf("copy object failed while move object: %w", err)
|
||||
}
|
||||
if _, err := c.client.Object.Delete(ctx, src, nil); err != nil {
|
||||
return fmt.Errorf("delete object failed while move object: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ObjectExists implements ObjectStorage
|
||||
func (c *storageCos) ObjectExists(ctx context.Context, objectName string) (bool, error) {
|
||||
return c.client.Object.IsExist(ctx, objectName)
|
||||
}
|
||||
@@ -10,9 +10,7 @@ import (
|
||||
"github.com/minio/minio-go/v7/pkg/credentials"
|
||||
)
|
||||
|
||||
var _ ObjectStorage = (*storageMinio)(nil)
|
||||
|
||||
type storageMinio struct {
|
||||
type StorageMinio struct {
|
||||
client *minio.Client
|
||||
|
||||
endpoint string
|
||||
@@ -23,7 +21,7 @@ type storageMinio struct {
|
||||
bucket string
|
||||
}
|
||||
|
||||
func newMinioStorage(endpoint, accessKey, accessSecret string, secure bool, bucket string) (ObjectStorage, error) {
|
||||
func newMinioStorage(endpoint, accessKey, accessSecret string, secure bool, bucket string) (*StorageMinio, error) {
|
||||
client, err := minio.New(endpoint, &minio.Options{
|
||||
Creds: credentials.NewStaticV4(accessKey, accessSecret, ""),
|
||||
Secure: secure,
|
||||
@@ -31,7 +29,7 @@ func newMinioStorage(endpoint, accessKey, accessSecret string, secure bool, buck
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &storageMinio{
|
||||
return &StorageMinio{
|
||||
client: client,
|
||||
endpoint: endpoint,
|
||||
accessKey: accessKey,
|
||||
@@ -42,39 +40,46 @@ func newMinioStorage(endpoint, accessKey, accessSecret string, secure bool, buck
|
||||
}
|
||||
|
||||
// PresignedPutObject implements ObjectStorage
|
||||
func (m *storageMinio) PresignedPutObject(ctx context.Context, objectName string, expires time.Duration) (u *url.URL, err error) {
|
||||
func (m *StorageMinio) PresignedPutObject(ctx context.Context, objectName string, expires time.Duration) (u *url.URL, err error) {
|
||||
return m.client.PresignedPutObject(ctx, m.bucket, objectName, expires)
|
||||
}
|
||||
|
||||
// PresignedGetObject implements ObjectStorage
|
||||
func (m *storageMinio) PresignedGetObject(ctx context.Context, objectName string, expires time.Duration) (u *url.URL, err error) {
|
||||
func (m *StorageMinio) PresignedGetObject(ctx context.Context, objectName string, expires time.Duration) (u *url.URL, err error) {
|
||||
return m.client.PresignedGetObject(ctx, m.bucket, objectName, expires, nil)
|
||||
}
|
||||
|
||||
// MoveObject implements ObjectStorage
|
||||
func (m *storageMinio) MoveObject(ctx context.Context, srcObject, dstObject string) (err error) {
|
||||
func (m *StorageMinio) MoveObject(ctx context.Context, srcObject, dstObject string) (err error) {
|
||||
dst := minio.CopyDestOptions{Bucket: m.bucket, Object: dstObject}
|
||||
src := minio.CopySrcOptions{Bucket: m.bucket, Object: srcObject}
|
||||
if _, err := m.client.CopyObject(ctx, dst, src); err != nil {
|
||||
return fmt.Errorf("move object failed while copy: %v", err)
|
||||
return fmt.Errorf("move object failed while copy: %w", err)
|
||||
}
|
||||
if err := m.client.RemoveObject(ctx, m.bucket, srcObject, minio.RemoveObjectOptions{}); err != nil {
|
||||
return fmt.Errorf("move object failed while remove: %v", err)
|
||||
return fmt.Errorf("move object failed while remove: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ObjectExists implements ObjectStorage
|
||||
func (m *storageMinio) ObjectExists(ctx context.Context, objectName string) (bool, error) {
|
||||
_, err := m.client.StatObject(ctx, m.bucket, objectName, minio.StatObjectOptions{})
|
||||
func (m *StorageMinio) ObjectStats(ctx context.Context, objectName string) (stat *minio.ObjectInfo, exists bool, err error) {
|
||||
obj, err := m.client.StatObject(ctx, m.bucket, objectName, minio.StatObjectOptions{})
|
||||
if err != nil {
|
||||
er := minio.ToErrorResponse(err)
|
||||
switch er.Code {
|
||||
switch minio.ToErrorResponse(err).Code {
|
||||
case "NoSuchKey", "NoSuchBucket":
|
||||
return false, nil
|
||||
return nil, false, nil
|
||||
default:
|
||||
return false, err
|
||||
return nil, false, err
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
return &obj, true, nil
|
||||
}
|
||||
|
||||
// MoveObject implements ObjectStorage
|
||||
func (m *StorageMinio) DeleteObject(ctx context.Context, objectName string) (err error) {
|
||||
if err := m.client.RemoveObject(ctx, m.bucket, objectName, minio.RemoveObjectOptions{}); err != nil {
|
||||
return fmt.Errorf("move object failed while remove: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user