gosdk/storage/minio.go

192 lines
4.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package storage
import (
"context"
"fmt"
"net/http"
"net/url"
"path"
"strings"
"time"
"github.com/minio/minio-go"
log "github.com/sirupsen/logrus"
)
type MinioConfig struct {
Bucket string
BaseUrl string
Endpoint string
AccessKey string
SecretKey string
Timeout time.Duration
}
type Minio struct {
inited bool
config *MinioConfig
client *minio.Client
}
func NewMinio(cfg *MinioConfig) Storage {
if cfg.Endpoint == "" {
u, _ := url.Parse(cfg.BaseUrl)
cfg.Endpoint = u.Host
}
return &Minio{
config: cfg,
inited: false,
}
}
func (s *Minio) Init() error {
if s.inited {
return nil
}
c, err := minio.New(s.config.Endpoint, s.config.AccessKey, s.config.SecretKey, false)
if err != nil {
return err
}
s.client = c
s.inited = true
return nil
}
func (s *Minio) Put(fileName, objectName string, onProcess func(fsize, uploaded int64)) error {
if err := s.Init(); err != nil {
return err
}
ctx, cancel := context.WithTimeout(context.Background(), s.config.Timeout)
defer cancel()
objectName = strings.TrimLeft(objectName, "/ ")
ext := strings.TrimLeft(path.Ext(fileName), ".")
_, err := s.client.FPutObjectWithContext(ctx, s.config.Bucket, objectName, fileName,
minio.PutObjectOptions{ContentType: ext2ContentType(ext)})
if err != nil {
log.Errorf("upload file to minio error:%s", err.Error())
return err
}
return nil
}
func (s *Minio) Del(objectName string) error {
if err := s.Init(); err != nil {
return err
}
err := s.client.RemoveObject(s.config.Bucket, objectName)
if err != nil {
log.Errorf("delete file to minio error:%s", err.Error())
return err
}
return nil
}
func (s *Minio) Get(objectName, fileName string) error {
if err := s.Init(); err != nil {
return err
}
return s.client.FGetObject(s.config.Bucket, objectName, fileName, minio.GetObjectOptions{})
}
func (s *Minio) List(objectPrefix string) ([]string, error) {
if err := s.Init(); err != nil {
return nil, err
}
done := make(chan struct{})
defer close(done)
infos := s.client.ListObjectsV2(s.config.Bucket, objectPrefix, true, done)
result := make([]string, 0)
for info := range infos {
result = append(result, info.Key)
}
return result, nil
}
func (s *Minio) Url(objectName string, expire time.Duration) string {
if err := s.Init(); err != nil {
return err.Error()
}
if expire > time.Hour*24*7 || expire == -1 {
expire = time.Hour * 24 * 7
}
var params url.Values
u, err := s.client.PresignedGetObject(s.config.Bucket, objectName, expire, params)
if err != nil {
log.Errorf("error:%s", err.Error())
return fmt.Sprintf("%s/%s/%s", s.config.BaseUrl, s.config.Bucket, objectName)
}
return u.String()
}
func (s *Minio) Stat(objectName string) (*ObjectInfo, error) {
if err := s.Init(); err != nil {
return nil, err
}
objectName = strings.TrimLeft(objectName, "/ ")
stat, err := s.client.StatObject(s.config.Bucket, objectName, minio.StatObjectOptions{})
if err != nil {
log.Errorf("stat object from minio error:%s", err.Error())
return nil, err
}
info := &ObjectInfo{
Size: stat.Size,
Hash: stat.ETag,
MimeType: stat.ContentType,
PutTime: stat.LastModified.Unix(),
}
return info, nil
}
func (s *Minio) Fetch(urlStr, objectName string) error {
if err := s.Init(); err != nil {
return err
}
// 从 URL 下载文件
resp, err := http.Get(urlStr)
if err != nil {
log.Errorf("fetch file from url error:%s", err.Error())
return err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("fetch file from url failed, status: %d", resp.StatusCode)
}
// 获取文件名和 Content-Type
objectName = strings.TrimLeft(objectName, "/ ")
// 优先根据文件扩展名推断 Content-Type确保图片能正确预览
ext := strings.TrimLeft(path.Ext(objectName), ".")
contentType := ext2ContentType(ext)
if contentType == "" {
contentType = resp.Header.Get("Content-Type")
}
// 上传到 MinIO
ctx, cancel := context.WithTimeout(context.Background(), s.config.Timeout)
defer cancel()
_, err = s.client.PutObjectWithContext(ctx, s.config.Bucket, objectName, resp.Body, resp.ContentLength,
minio.PutObjectOptions{ContentType: contentType})
if err != nil {
log.Errorf("upload fetched file to minio error:%s", err.Error())
return err
}
return nil
}