mirror of
https://github.com/openimsdk/open-im-server.git
synced 2026-01-07 12:17:02 +08:00
feat: minio
This commit is contained in:
parent
cf815dcf71
commit
94be8fc0c4
@ -135,6 +135,7 @@ object:
|
||||
sessionToken: ""
|
||||
signEndpoint: "http://127.0.0.1:10005"
|
||||
thumbnailApi: "http://127.0.0.1:10003"
|
||||
thumbnailUseSignEndpoint: false
|
||||
cos:
|
||||
bucketURL: "https://temp-1252357374.cos.ap-chengdu.myqcloud.com"
|
||||
secretID: ""
|
||||
|
||||
2
go.mod
2
go.mod
@ -37,7 +37,7 @@ require (
|
||||
require github.com/google/uuid v1.3.0
|
||||
|
||||
require (
|
||||
github.com/OpenIMSDK/protocol v0.0.3
|
||||
github.com/OpenIMSDK/protocol v0.0.6
|
||||
github.com/OpenIMSDK/tools v0.0.13
|
||||
github.com/aliyun/aliyun-oss-go-sdk v2.2.7+incompatible
|
||||
github.com/go-redis/redis v6.15.9+incompatible
|
||||
|
||||
4
go.sum
4
go.sum
@ -17,8 +17,8 @@ cloud.google.com/go/storage v1.30.1/go.mod h1:NfxhC0UJE1aXSx7CIIbCf7y9HKT7Biccwk
|
||||
firebase.google.com/go v3.13.0+incompatible h1:3TdYC3DDi6aHn20qoRkxwGqNgdjtblwVAyRLQwGn/+4=
|
||||
firebase.google.com/go v3.13.0+incompatible/go.mod h1:xlah6XbEyW6tbfSklcfe5FHJIwjt8toICdV5Wh9ptHs=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/OpenIMSDK/protocol v0.0.3 h1:CFQtmnyW+1dYKVFaVaHcJ6oYuMiMdNfU2gC1xz3K/9I=
|
||||
github.com/OpenIMSDK/protocol v0.0.3/go.mod h1:F25dFrwrIx3lkNoiuf6FkCfxuwf8L4Z8UIsdTHP/r0Y=
|
||||
github.com/OpenIMSDK/protocol v0.0.6 h1:KjaItOEww7vjrhwyxHnVzhw80pnjcNukpskadqW6gnA=
|
||||
github.com/OpenIMSDK/protocol v0.0.6/go.mod h1:F25dFrwrIx3lkNoiuf6FkCfxuwf8L4Z8UIsdTHP/r0Y=
|
||||
github.com/OpenIMSDK/tools v0.0.13 h1:rcw4HS8S2DPZR9UOBxD8/ol9UBMzXBypzOVEytDRIMo=
|
||||
github.com/OpenIMSDK/tools v0.0.13/go.mod h1:eg+q4A34Qmu73xkY0mt37FHGMCMfC6CtmOnm0kFEGFI=
|
||||
github.com/QcloudApi/qcloud_sign_golang v0.0.0-20141224014652-e4130a326409/go.mod h1:1pk82RBxDY/JZnPQrtqHlUFfCctgdorsd9M06fMynOM=
|
||||
|
||||
@ -81,7 +81,14 @@ func (o *ThirdApi) ObjectRedirect(c *gin.Context) {
|
||||
operationID = strconv.Itoa(rand.Int())
|
||||
}
|
||||
ctx := mcontext.SetOperationID(c, operationID)
|
||||
resp, err := o.Client.AccessURL(ctx, &third.AccessURLReq{Name: name})
|
||||
query := make(map[string]string)
|
||||
for key, values := range c.Request.URL.Query() {
|
||||
if len(values) == 0 {
|
||||
continue
|
||||
}
|
||||
query[key] = values[0]
|
||||
}
|
||||
resp, err := o.Client.AccessURL(ctx, &third.AccessURLReq{Name: name, Query: query})
|
||||
if err != nil {
|
||||
if errs.ErrArgs.Is(err) {
|
||||
c.String(http.StatusBadRequest, err.Error())
|
||||
|
||||
@ -16,6 +16,8 @@ package third
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/OpenIMSDK/Open-IM-Server/pkg/common/db/s3"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/OpenIMSDK/Open-IM-Server/pkg/common/db/s3/cont"
|
||||
@ -151,7 +153,22 @@ func (t *thirdServer) CompleteMultipartUpload(ctx context.Context, req *third.Co
|
||||
}
|
||||
|
||||
func (t *thirdServer) AccessURL(ctx context.Context, req *third.AccessURLReq) (*third.AccessURLResp, error) {
|
||||
expireTime, rawURL, err := t.s3dataBase.AccessURL(ctx, req.Name, t.defaultExpire)
|
||||
opt := &s3.AccessURLOption{}
|
||||
if len(req.Query) > 0 {
|
||||
switch req.Query["type"] {
|
||||
case "image":
|
||||
opt.Image.Format = req.Query["format"]
|
||||
opt.Image.Width, _ = strconv.Atoi(req.Query["width"])
|
||||
opt.Image.Height, _ = strconv.Atoi(req.Query["height"])
|
||||
case "video":
|
||||
opt.Video.Format = req.Query["format"]
|
||||
opt.Video.Width, _ = strconv.Atoi(req.Query["width"])
|
||||
opt.Video.Height, _ = strconv.Atoi(req.Query["height"])
|
||||
millisecond, _ := strconv.Atoi(req.Query["time"])
|
||||
opt.Video.Time = time.Millisecond * time.Duration(millisecond)
|
||||
}
|
||||
}
|
||||
expireTime, rawURL, err := t.s3dataBase.AccessURL(ctx, req.Name, t.defaultExpire, opt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@ -119,8 +119,9 @@ type configStruct struct {
|
||||
AccessKeyID string `yaml:"accessKeyID"`
|
||||
SecretAccessKey string `yaml:"secretAccessKey"`
|
||||
SessionToken string `yaml:"sessionToken"`
|
||||
ThumbnailApi string `yaml:"thumbnailApi"`
|
||||
SignEndpoint string `yaml:"signEndpoint"`
|
||||
ThumbnailApi string `yaml:"thumbnailApi"`
|
||||
ThumbnailUseSignEndpoint bool `yaml:"thumbnailUseSignEndpoint"`
|
||||
} `yaml:"minio"`
|
||||
Cos struct {
|
||||
BucketURL string `yaml:"bucketURL"`
|
||||
|
||||
@ -30,7 +30,7 @@ type S3Database interface {
|
||||
AuthSign(ctx context.Context, uploadID string, partNumbers []int) (*s3.AuthSignResult, error)
|
||||
InitiateMultipartUpload(ctx context.Context, hash string, size int64, expire time.Duration, maxParts int) (*cont.InitiateUploadResult, error)
|
||||
CompleteMultipartUpload(ctx context.Context, uploadID string, parts []string) (*cont.UploadResult, error)
|
||||
AccessURL(ctx context.Context, name string, expire time.Duration) (time.Time, string, error)
|
||||
AccessURL(ctx context.Context, name string, expire time.Duration, opt *s3.AccessURLOption) (time.Time, string, error)
|
||||
SetObject(ctx context.Context, info *relation.ObjectModel) error
|
||||
}
|
||||
|
||||
@ -70,14 +70,19 @@ func (s *s3Database) SetObject(ctx context.Context, info *relation.ObjectModel)
|
||||
return s.obj.SetObject(ctx, info)
|
||||
}
|
||||
|
||||
func (s *s3Database) AccessURL(ctx context.Context, name string, expire time.Duration) (time.Time, string, error) {
|
||||
func (s *s3Database) AccessURL(ctx context.Context, name string, expire time.Duration, opt *s3.AccessURLOption) (time.Time, string, error) {
|
||||
obj, err := s.obj.Take(ctx, name)
|
||||
if err != nil {
|
||||
return time.Time{}, "", err
|
||||
}
|
||||
opt := &s3.AccessURLOption{
|
||||
ContentType: obj.ContentType,
|
||||
Filename: filepath.Base(obj.Name),
|
||||
if opt == nil {
|
||||
opt = &s3.AccessURLOption{}
|
||||
}
|
||||
if opt.ContentType == "" {
|
||||
opt.ContentType = obj.ContentType
|
||||
}
|
||||
if opt.Filename == "" {
|
||||
opt.Filename = filepath.Base(obj.Name)
|
||||
}
|
||||
expireTime := time.Now().Add(expire)
|
||||
rawURL, err := s.s3.AccessURL(ctx, obj.Key, expire, opt)
|
||||
|
||||
@ -308,19 +308,19 @@ func (c *Cos) AccessURL(ctx context.Context, name string, expire time.Duration,
|
||||
sec = 0
|
||||
}
|
||||
query.Set("time", strconv.FormatFloat(sec, 'f', 3, 64))
|
||||
switch opt.Video.ImageFormat {
|
||||
switch opt.Video.Format {
|
||||
case
|
||||
videoSnapshotImagePng,
|
||||
videoSnapshotImageJpg:
|
||||
default:
|
||||
opt.Video.ImageFormat = videoSnapshotImageJpg
|
||||
opt.Video.Format = videoSnapshotImageJpg
|
||||
}
|
||||
query.Set("format", opt.Video.ImageFormat)
|
||||
opt.ContentType = "image/" + opt.Video.ImageFormat
|
||||
query.Set("format", opt.Video.Format)
|
||||
opt.ContentType = "image/" + opt.Video.Format
|
||||
if opt.Filename == "" {
|
||||
opt.Filename = filepath.Base(name) + "." + opt.Video.ImageFormat
|
||||
} else if filepath.Ext(opt.Filename) != "."+opt.Video.ImageFormat {
|
||||
opt.Filename += "." + opt.Video.ImageFormat
|
||||
opt.Filename = filepath.Base(name) + "." + opt.Video.Format
|
||||
} else if filepath.Ext(opt.Filename) != "."+opt.Video.Format {
|
||||
opt.Filename += "." + opt.Video.Format
|
||||
}
|
||||
if opt.Video.Width > 0 {
|
||||
query.Set("width", strconv.Itoa(opt.Video.Width))
|
||||
|
||||
@ -71,6 +71,7 @@ func NewMinio() (s3.Interface, error) {
|
||||
bucket: conf.Bucket,
|
||||
bucketURL: conf.Endpoint + "/" + conf.Bucket + "/",
|
||||
imageApi: imageApi,
|
||||
imageUseSignAddr: conf.ThumbnailUseSignEndpoint,
|
||||
core: &minio.Core{Client: client},
|
||||
lock: &sync.Mutex{},
|
||||
init: false,
|
||||
@ -103,6 +104,7 @@ type Minio struct {
|
||||
bucket string
|
||||
bucketURL string
|
||||
imageApi string
|
||||
imageUseSignAddr bool
|
||||
location string
|
||||
opts *minio.Options
|
||||
core *minio.Core
|
||||
@ -369,7 +371,13 @@ func (m *Minio) AccessURL(ctx context.Context, name string, expire time.Duration
|
||||
} else if expire < time.Second {
|
||||
expire = time.Second
|
||||
}
|
||||
u, err := m.sign.PresignedGetObject(ctx, m.bucket, name, expire, reqParams)
|
||||
var client *minio.Client
|
||||
if m.imageUseSignAddr {
|
||||
client = m.sign
|
||||
} else {
|
||||
client = m.core.Client
|
||||
}
|
||||
u, err := client.PresignedGetObject(ctx, m.bucket, name, expire, reqParams)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
@ -291,9 +291,9 @@ func (o *OSS) AccessURL(ctx context.Context, name string, expire time.Duration,
|
||||
}
|
||||
opt.ContentType = "image/" + format
|
||||
if opt.Filename == "" {
|
||||
opt.Filename = filepath.Base(name) + "." + opt.Video.ImageFormat
|
||||
} else if filepath.Ext(opt.Filename) != "."+opt.Video.ImageFormat {
|
||||
opt.Filename += "." + opt.Video.ImageFormat
|
||||
opt.Filename = filepath.Base(name) + "." + opt.Video.Format
|
||||
} else if filepath.Ext(opt.Filename) != "."+opt.Video.Format {
|
||||
opt.Filename += "." + opt.Video.Format
|
||||
}
|
||||
// https://oss-console-img-demo-cn-hangzhou.oss-cn-hangzhou.aliyuncs.com/example.jpg?x-oss-process=image/resize,h_100,m_lfit
|
||||
process := "image/resize,m_lfit"
|
||||
@ -313,18 +313,18 @@ func (o *OSS) AccessURL(ctx context.Context, name string, expire time.Duration,
|
||||
if millisecond < 0 {
|
||||
millisecond = 0
|
||||
}
|
||||
switch opt.Video.ImageFormat {
|
||||
switch opt.Video.Format {
|
||||
case videoSnapshotImageJpg, videoSnapshotImagePng:
|
||||
default:
|
||||
opt.Video.ImageFormat = videoSnapshotImageJpg
|
||||
opt.Video.Format = videoSnapshotImageJpg
|
||||
}
|
||||
opt.ContentType = "image/" + opt.Video.ImageFormat
|
||||
opt.ContentType = "image/" + opt.Video.Format
|
||||
if opt.Filename == "" {
|
||||
opt.Filename = filepath.Base(name) + "." + opt.Video.ImageFormat
|
||||
} else if filepath.Ext(opt.Filename) != "."+opt.Video.ImageFormat {
|
||||
opt.Filename += "." + opt.Video.ImageFormat
|
||||
opt.Filename = filepath.Base(name) + "." + opt.Video.Format
|
||||
} else if filepath.Ext(opt.Filename) != "."+opt.Video.Format {
|
||||
opt.Filename += "." + opt.Video.Format
|
||||
}
|
||||
process := "video/snapshot,t_" + strconv.Itoa(millisecond) + ",f_" + opt.Video.ImageFormat
|
||||
process := "video/snapshot,t_" + strconv.Itoa(millisecond) + ",f_" + opt.Video.Format
|
||||
if opt.Video.Width > 0 {
|
||||
process += ",w_" + strconv.Itoa(opt.Video.Width)
|
||||
}
|
||||
|
||||
@ -126,7 +126,7 @@ type Video struct {
|
||||
Width int `json:"width"`
|
||||
Height int `json:"height"`
|
||||
Time time.Duration `json:"time"`
|
||||
ImageFormat string `json:"format"`
|
||||
Format string `json:"format"`
|
||||
}
|
||||
|
||||
type AccessURLOption struct {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user