mirror of
https://github.com/openimsdk/open-im-server.git
synced 2026-05-15 06:25:58 +08:00
api rpc third
This commit is contained in:
@@ -0,0 +1,183 @@
|
||||
package obj
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/minio/minio-go/v7"
|
||||
"github.com/minio/minio-go/v7/pkg/s3utils"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
func NewMinioClient() {
|
||||
|
||||
}
|
||||
|
||||
func NewMinioInterface() (Interface, error) {
|
||||
//client, err := minio.New("127.0.0.1:9000", &minio.Options{
|
||||
// Creds: credentials.NewStaticV4("minioadmin", "minioadmin", ""),
|
||||
// Secure: false,
|
||||
//})
|
||||
|
||||
return &minioImpl{}, nil
|
||||
}
|
||||
|
||||
type minioImpl struct {
|
||||
tempBucket string // 上传桶
|
||||
permanentBucket string // 永久桶
|
||||
clearBucket string // 自动清理桶
|
||||
urlstr string // 访问地址
|
||||
client *minio.Client
|
||||
}
|
||||
|
||||
//func (m *minioImpl) Init() error {
|
||||
// client, err := minio.New("127.0.0.1:9000", &minio.Options{
|
||||
// Creds: credentials.NewStaticV4("minioadmin", "minioadmin", ""),
|
||||
// Secure: false,
|
||||
// })
|
||||
// if err != nil {
|
||||
// return fmt.Errorf("minio client error: %w", err)
|
||||
// }
|
||||
// m.urlstr = "http://127.0.0.1:9000"
|
||||
// m.client = client
|
||||
// m.tempBucket = "temp"
|
||||
// m.permanentBucket = "permanent"
|
||||
// m.clearBucket = "clear"
|
||||
// return nil
|
||||
//}
|
||||
|
||||
func (m *minioImpl) Name() string {
|
||||
return "minio"
|
||||
}
|
||||
|
||||
func (m *minioImpl) MinFragmentSize() int64 {
|
||||
return 1024 * 1024 * 5 // 每个分片最小大小 minio.absMinPartSize
|
||||
}
|
||||
|
||||
func (m *minioImpl) MaxFragmentNum() int {
|
||||
return 1000 // 最大分片数量 minio.maxPartsCount
|
||||
}
|
||||
|
||||
func (m *minioImpl) MinExpirationTime() time.Duration {
|
||||
return time.Hour * 24
|
||||
}
|
||||
|
||||
func (m *minioImpl) AppendHeader() http.Header {
|
||||
return map[string][]string{
|
||||
"x-amz-object-append": {"true"},
|
||||
}
|
||||
}
|
||||
|
||||
func (m *minioImpl) TempBucket() string {
|
||||
return m.tempBucket
|
||||
}
|
||||
|
||||
func (m *minioImpl) DataBucket() string {
|
||||
return m.permanentBucket
|
||||
}
|
||||
|
||||
func (m *minioImpl) ClearBucket() string {
|
||||
return m.clearBucket
|
||||
}
|
||||
|
||||
func (m *minioImpl) GetURL(bucket string, name string) string {
|
||||
return fmt.Sprintf("%s/%s/%s", m.urlstr, bucket, name)
|
||||
}
|
||||
|
||||
func (m *minioImpl) PresignedPutURL(ctx context.Context, args *ApplyPutArgs) (string, error) {
|
||||
if args.Effective <= 0 {
|
||||
return "", errors.New("EffectiveTime <= 0")
|
||||
}
|
||||
_, err := m.GetObjectInfo(ctx, &BucketObject{
|
||||
Bucket: m.tempBucket,
|
||||
Name: args.Name,
|
||||
})
|
||||
if err == nil {
|
||||
return "", fmt.Errorf("minio bucket %s name %s already exists", args.Bucket, args.Name)
|
||||
} else if !m.IsNotFound(err) {
|
||||
return "", err
|
||||
}
|
||||
u, err := m.client.PresignedPutObject(ctx, m.tempBucket, args.Name, args.Effective)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("minio apply error: %w", err)
|
||||
}
|
||||
return u.String(), nil
|
||||
}
|
||||
|
||||
func (m *minioImpl) GetObjectInfo(ctx context.Context, args *BucketObject) (*ObjectInfo, error) {
|
||||
info, err := m.client.StatObject(ctx, args.Bucket, args.Name, minio.StatObjectOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ObjectInfo{
|
||||
URL: m.GetURL(args.Bucket, args.Name),
|
||||
Size: info.Size,
|
||||
Hash: info.ETag,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (m *minioImpl) CopyObjet(ctx context.Context, src *BucketObject, dst *BucketObject) error {
|
||||
_, err := m.client.CopyObject(ctx, minio.CopyDestOptions{
|
||||
Bucket: dst.Bucket,
|
||||
Object: dst.Name,
|
||||
}, minio.CopySrcOptions{
|
||||
Bucket: src.Bucket,
|
||||
Object: src.Name,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (m *minioImpl) DeleteObjet(ctx context.Context, info *BucketObject) error {
|
||||
return m.client.RemoveObject(ctx, info.Bucket, info.Name, minio.RemoveObjectOptions{})
|
||||
}
|
||||
|
||||
func (m *minioImpl) MoveObjetInfo(ctx context.Context, src *BucketObject, dst *BucketObject) error {
|
||||
if err := m.CopyObjet(ctx, src, dst); err != nil {
|
||||
return err
|
||||
}
|
||||
return m.DeleteObjet(ctx, src)
|
||||
}
|
||||
|
||||
func (m *minioImpl) ComposeObject(ctx context.Context, src []BucketObject, dst *BucketObject) error {
|
||||
destOptions := minio.CopyDestOptions{
|
||||
Bucket: dst.Bucket,
|
||||
Object: dst.Name + ".temp",
|
||||
}
|
||||
sources := make([]minio.CopySrcOptions, len(src))
|
||||
for i, s := range src {
|
||||
sources[i] = minio.CopySrcOptions{
|
||||
Bucket: s.Bucket,
|
||||
Object: s.Name,
|
||||
}
|
||||
}
|
||||
_, err := m.client.ComposeObject(ctx, destOptions, sources...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return m.MoveObjetInfo(ctx, &BucketObject{
|
||||
Bucket: destOptions.Bucket,
|
||||
Name: destOptions.Object,
|
||||
}, &BucketObject{
|
||||
Bucket: dst.Bucket,
|
||||
Name: dst.Name,
|
||||
})
|
||||
}
|
||||
|
||||
func (m *minioImpl) IsNotFound(err error) bool {
|
||||
if err == nil {
|
||||
return false
|
||||
}
|
||||
switch e := err.(type) {
|
||||
case minio.ErrorResponse:
|
||||
return e.StatusCode == 404 && e.Code == "NoSuchKey"
|
||||
case *minio.ErrorResponse:
|
||||
return e.StatusCode == 404 && e.Code == "NoSuchKey"
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func (m *minioImpl) CheckName(name string) error {
|
||||
return s3utils.CheckValidObjectName(name)
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package obj
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
type BucketObject struct {
|
||||
Bucket string `json:"bucket"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
type ApplyPutArgs struct {
|
||||
Bucket string
|
||||
Name string
|
||||
Effective time.Duration // 申请有效时间
|
||||
Header http.Header // header
|
||||
MaxObjectSize int64
|
||||
}
|
||||
|
||||
type ObjectInfo struct {
|
||||
URL string
|
||||
Size int64
|
||||
Hash string
|
||||
Expiration time.Time
|
||||
}
|
||||
|
||||
type Interface interface {
|
||||
// Name 存储名字
|
||||
Name() string
|
||||
// MinFragmentSize 最小允许的分片大小
|
||||
MinFragmentSize() int64
|
||||
// MaxFragmentNum 最大允许的分片数量
|
||||
MaxFragmentNum() int
|
||||
// MinExpirationTime 最小过期时间
|
||||
MinExpirationTime() time.Duration
|
||||
// TempBucket 临时桶名,用于上传
|
||||
TempBucket() string
|
||||
// DataBucket 永久存储的桶名
|
||||
DataBucket() string
|
||||
// GetURL 通过桶名和对象名返回URL
|
||||
GetURL(bucket string, name string) string
|
||||
// PresignedPutURL 申请上传,返回PUT的上传地址
|
||||
PresignedPutURL(ctx context.Context, args *ApplyPutArgs) (string, error)
|
||||
// GetObjectInfo 获取对象信息
|
||||
GetObjectInfo(ctx context.Context, args *BucketObject) (*ObjectInfo, error)
|
||||
// CopyObjet 复制对象
|
||||
CopyObjet(ctx context.Context, src *BucketObject, dst *BucketObject) error
|
||||
// DeleteObjet 删除对象
|
||||
DeleteObjet(ctx context.Context, info *BucketObject) error
|
||||
// ComposeObject 合并对象
|
||||
ComposeObject(ctx context.Context, src []BucketObject, dst *BucketObject) error
|
||||
// IsNotFound 判断是不是不存在导致的错误
|
||||
IsNotFound(err error) bool
|
||||
// CheckName 检查名字是否可用
|
||||
CheckName(name string) error
|
||||
}
|
||||
Reference in New Issue
Block a user