121 lines
2.9 KiB
Go
121 lines
2.9 KiB
Go
// MinIO 对象存储客户端封装
|
||
package minio
|
||
|
||
import (
|
||
"bytes"
|
||
"context"
|
||
"fmt"
|
||
"io"
|
||
"path/filepath"
|
||
"time"
|
||
|
||
myconfig "com.sclktx/m/v2/internal/pkg/config"
|
||
|
||
"github.com/google/uuid"
|
||
"github.com/minio/minio-go/v7"
|
||
"github.com/minio/minio-go/v7/pkg/credentials"
|
||
)
|
||
|
||
// Client MinIO 客户端
|
||
type Client struct {
|
||
client *minio.Client
|
||
config *myconfig.MinIOConfig
|
||
}
|
||
|
||
// NewClient 创建 MinIO 客户端
|
||
func NewClient(cfg *myconfig.MinIOConfig) (*Client, error) {
|
||
minioClient, err := minio.New(cfg.Endpoint, &minio.Options{
|
||
Creds: credentials.NewStaticV4(cfg.AccessKey, cfg.SecretKey, ""),
|
||
Secure: cfg.UseSSL,
|
||
})
|
||
if err != nil {
|
||
return nil, fmt.Errorf("创建 MinIO 客户端失败:%w", err)
|
||
}
|
||
|
||
// 确保 bucket 存在
|
||
ctx := context.Background()
|
||
exists, err := minioClient.BucketExists(ctx, cfg.Bucket)
|
||
if err != nil {
|
||
return nil, fmt.Errorf("检查 bucket 失败:%w", err)
|
||
}
|
||
|
||
if !exists {
|
||
// 创建 bucket
|
||
err = minioClient.MakeBucket(ctx, cfg.Bucket, minio.MakeBucketOptions{})
|
||
if err != nil {
|
||
return nil, fmt.Errorf("创建 bucket 失败:%w", err)
|
||
}
|
||
}
|
||
|
||
return &Client{
|
||
client: minioClient,
|
||
config: cfg,
|
||
}, nil
|
||
}
|
||
|
||
// UploadFile 上传文件到 MinIO
|
||
// 返回文件的公开访问 URL
|
||
func (c *Client) UploadFile(ctx context.Context, reader io.Reader, objectName string, contentType string) (string, error) {
|
||
// 上传文件
|
||
info, err := c.client.PutObject(ctx, c.config.Bucket, objectName, reader, -1, minio.PutObjectOptions{
|
||
ContentType: contentType,
|
||
})
|
||
if err != nil {
|
||
return "", fmt.Errorf("上传文件失败:%w", err)
|
||
}
|
||
|
||
// 生成公开访问 URL(不带签名,永久有效)
|
||
// 如果配置了 base_url(可带协议如 https://),直接使用
|
||
// 否则用 endpoint(需自行保证协议正确)
|
||
urlBase := c.config.BaseURL
|
||
if urlBase == "" {
|
||
urlBase = c.config.Endpoint
|
||
}
|
||
url := fmt.Sprintf("%s/%s/%s", urlBase, c.config.Bucket, info.Key)
|
||
return url, nil
|
||
}
|
||
|
||
// UploadImage 上传图片文件
|
||
// 自动生成唯一的文件名(UUID + 时间戳 + 扩展名)
|
||
func (c *Client) UploadImage(ctx context.Context, data []byte, filename string) (string, error) {
|
||
// 生成唯一的文件名
|
||
ext := filepath.Ext(filename)
|
||
if ext == "" {
|
||
ext = ".jpg" // 默认扩展名
|
||
}
|
||
|
||
// 使用 UUID + 时间戳生成唯一文件名
|
||
objectName := fmt.Sprintf("images/%s_%s%s",
|
||
time.Now().Format("20060102150405"),
|
||
uuid.New().String()[:8],
|
||
ext,
|
||
)
|
||
|
||
// 判断内容类型
|
||
contentType := "image/jpeg"
|
||
switch ext {
|
||
case ".png":
|
||
contentType = "image/png"
|
||
case ".gif":
|
||
contentType = "image/gif"
|
||
case ".webp":
|
||
contentType = "image/webp"
|
||
case ".jpg", ".jpeg":
|
||
contentType = "image/jpeg"
|
||
}
|
||
|
||
// 上传
|
||
reader := bytes.NewReader(data)
|
||
return c.UploadFile(ctx, reader, objectName, contentType)
|
||
}
|
||
|
||
// GetClient 获取原始 MinIO 客户端
|
||
func (c *Client) GetClient() *minio.Client {
|
||
return c.client
|
||
}
|
||
|
||
// GetConfig 获取配置
|
||
func (c *Client) GetConfig() *myconfig.MinIOConfig {
|
||
return c.config
|
||
}
|