feat(api): docs & folders basid curd implemention

This commit is contained in:
neo-f
2023-03-23 17:43:27 +08:00
parent 005a13d8a5
commit a5545401d8
19 changed files with 1304 additions and 222 deletions

View File

@@ -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"))

View File

@@ -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)
}

View File

@@ -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
}