Skip to content

Commit b538543

Browse files
committed
feat: upgrade oss
1 parent cd478e2 commit b538543

File tree

8 files changed

+437
-15
lines changed

8 files changed

+437
-15
lines changed

components/oss/meta/oss.go

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package meta
2+
3+
import (
4+
"context"
5+
"io"
6+
"time"
7+
)
8+
9+
// ClientType 存储类型枚举
10+
type ClientType string
11+
12+
const (
13+
ClientTypeMinio ClientType = "minio"
14+
)
15+
16+
// Config 存储配置
17+
type Config struct {
18+
Type ClientType // 客户端类型
19+
Endpoint string // 服务端点
20+
AccessKey string // 访问密钥
21+
SecretKey string // 秘密密钥
22+
Region string // 区域(S3需要)
23+
SSL bool // 是否使用SSL
24+
BucketName string // 默认存储桶名称
25+
}
26+
27+
// OSSClient 抽象接口
28+
type OSSClient interface {
29+
PutObject(ctx context.Context, objectKey string, reader io.Reader, objectSize int64) error
30+
GetObject(ctx context.Context, objectKey string) (io.ReadCloser, error)
31+
RemoveObject(ctx context.Context, objectKey string) error
32+
StatObject(ctx context.Context, objectKey string) (ObjectInfo, error)
33+
PresignedGetObject(ctx context.Context, objectKey string, expiry time.Duration) (string, error)
34+
CreateBucket(ctx context.Context, bucketName string) error
35+
ListObjects(ctx context.Context, bucketName string, prefix string, recursive bool) ([]ObjectInfo, error)
36+
RemoveBucket(ctx context.Context, bucketName string) error
37+
Bucket(ctx context.Context, bucketName string) OSSClient
38+
}
39+
40+
// ObjectInfo 对象元数据
41+
type ObjectInfo struct {
42+
ETag string
43+
Key string
44+
Size int64
45+
LastModified time.Time
46+
ContentType string
47+
}

components/oss/minio/minio.go

+99
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
package minio
2+
3+
import (
4+
"context"
5+
"io"
6+
"log"
7+
"time"
8+
9+
"github.com/alomerry/go-tools/components/oss/meta"
10+
minio "github.com/minio/minio-go/v7"
11+
"github.com/minio/minio-go/v7/pkg/credentials"
12+
)
13+
14+
type minioClient struct {
15+
client *minio.Client
16+
bucketName string
17+
}
18+
19+
func NewMinioClient(cfg meta.Config) (meta.OSSClient, error) {
20+
client, err := minio.New(cfg.Endpoint, &minio.Options{
21+
Creds: credentials.NewStaticV4(cfg.AccessKey, cfg.SecretKey, ""),
22+
Secure: cfg.SSL,
23+
})
24+
if err != nil {
25+
log.Fatalln("初始化客户端失败:", err)
26+
}
27+
log.Printf("MinIO 客户端已连接: %#v\n", client)
28+
return &minioClient{
29+
client: client,
30+
bucketName: cfg.BucketName,
31+
}, nil
32+
}
33+
34+
func (m *minioClient) PutObject(ctx context.Context, objectKey string, reader io.Reader, objectSize int64) error {
35+
_, err := m.client.PutObject(ctx, m.bucketName, objectKey, reader, objectSize, minio.PutObjectOptions{})
36+
return err
37+
}
38+
39+
func (m *minioClient) Bucket(ctx context.Context, bucketName string) meta.OSSClient {
40+
return &minioClient{
41+
client: m.client,
42+
bucketName: bucketName,
43+
}
44+
}
45+
46+
func (m *minioClient) GetObject(ctx context.Context, objectKey string) (io.ReadCloser, error) {
47+
return m.client.GetObject(ctx, m.bucketName, objectKey, minio.GetObjectOptions{})
48+
}
49+
50+
func (m *minioClient) RemoveObject(ctx context.Context, objectKey string) error {
51+
return m.client.RemoveObject(ctx, m.bucketName, objectKey, minio.RemoveObjectOptions{})
52+
}
53+
54+
func (m *minioClient) StatObject(ctx context.Context, objectKey string) (meta.ObjectInfo, error) {
55+
info, err := m.client.StatObject(ctx, m.bucketName, objectKey, minio.StatObjectOptions{})
56+
if err != nil {
57+
return meta.ObjectInfo{}, err
58+
}
59+
60+
return meta.ObjectInfo{
61+
ETag: info.ETag,
62+
Key: info.Key,
63+
Size: info.Size,
64+
LastModified: info.LastModified,
65+
ContentType: info.ContentType,
66+
}, nil
67+
}
68+
69+
func (m *minioClient) PresignedGetObject(ctx context.Context, objectKey string, expiry time.Duration) (string, error) {
70+
url, err := m.client.PresignedGetObject(ctx, m.bucketName, objectKey, expiry, nil)
71+
if err != nil {
72+
return "", err
73+
}
74+
return url.String(), nil
75+
}
76+
77+
func (m *minioClient) CreateBucket(ctx context.Context, bucketName string) error {
78+
return m.client.MakeBucket(ctx, bucketName, minio.MakeBucketOptions{})
79+
}
80+
81+
func (m *minioClient) ListObjects(ctx context.Context, bucketName string, prefix string, recursive bool) ([]meta.ObjectInfo, error) {
82+
objects := m.client.ListObjects(ctx, bucketName, minio.ListObjectsOptions{
83+
Prefix: prefix,
84+
Recursive: recursive,
85+
})
86+
87+
results := make([]meta.ObjectInfo, 0)
88+
for object := range objects {
89+
results = append(results, meta.ObjectInfo{
90+
ETag: object.ETag,
91+
})
92+
}
93+
94+
return results, nil
95+
}
96+
97+
func (m *minioClient) RemoveBucket(ctx context.Context, bucketName string) error {
98+
return m.client.RemoveBucket(ctx, bucketName)
99+
}

components/oss/minio/minio_test.go

+201
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
package minio
2+
3+
import (
4+
"context"
5+
"io"
6+
"strings"
7+
"testing"
8+
"time"
9+
10+
"github.com/alomerry/go-tools/components/oss/meta"
11+
"github.com/alomerry/go-tools/static/env/oss"
12+
)
13+
14+
var (
15+
cfg = meta.Config{
16+
Type: meta.ClientTypeMinio,
17+
Endpoint: oss.MinioEndpoint(),
18+
AccessKey: "minioadmin",
19+
SecretKey: "minioadmin",
20+
}
21+
)
22+
23+
func TestMinioClient_PutObject(t *testing.T) {
24+
cfg.SSL = false
25+
26+
client, err := NewMinioClient(cfg)
27+
if err != nil {
28+
t.Fatalf("Failed to create minio client: %v", err)
29+
}
30+
31+
objectKey := "homelab/test.txt"
32+
objectContent := "Hello, Minio!"
33+
34+
err = client.Bucket(context.Background(), "homelab").PutObject(context.Background(), objectKey, strings.NewReader(objectContent), int64(len(objectContent)))
35+
if err != nil {
36+
t.Fatalf("Failed to put object: %v", err)
37+
}
38+
39+
t.Logf("Object %s uploaded successfully", objectKey)
40+
}
41+
42+
func TestMinioClient_GetObject(t *testing.T) {
43+
cfg.SSL = false
44+
cfg.BucketName = "homelab"
45+
46+
client, err := NewMinioClient(cfg)
47+
if err != nil {
48+
t.Fatalf("Failed to create minio client: %v", err)
49+
}
50+
51+
objectKey := "homelab/test.txt"
52+
reader, err := client.GetObject(context.Background(), objectKey)
53+
if err != nil {
54+
t.Fatalf("Failed to get object: %v", err)
55+
}
56+
57+
content, err := io.ReadAll(reader)
58+
if err != nil {
59+
t.Fatalf("Failed to read object content: %v", err)
60+
}
61+
62+
t.Logf("Object %s content: %s", objectKey, string(content))
63+
}
64+
65+
func TestMinioClient_RemoveObject(t *testing.T) {
66+
cfg.SSL = false
67+
cfg.BucketName = "homelab"
68+
69+
client, err := NewMinioClient(cfg)
70+
if err != nil {
71+
t.Fatalf("Failed to create minio client: %v", err)
72+
}
73+
74+
objectKey := "homelab/test.txt"
75+
76+
err = client.RemoveObject(context.Background(), objectKey)
77+
if err != nil {
78+
t.Fatalf("Failed to remove object: %v", err)
79+
}
80+
81+
t.Logf("Object %s removed successfully", objectKey)
82+
}
83+
84+
func TestMinioClient_StatObject(t *testing.T) {
85+
cfg.SSL = false
86+
cfg.BucketName = "homelab"
87+
88+
client, err := NewMinioClient(cfg)
89+
if err != nil {
90+
t.Fatalf("Failed to create minio client: %v", err)
91+
}
92+
93+
objectKey := "homelab/test.txt"
94+
95+
info, err := client.StatObject(context.Background(), objectKey)
96+
if err != nil {
97+
t.Fatalf("Failed to stat object: %v", err)
98+
}
99+
100+
t.Logf("Object %s info: %+v", objectKey, info)
101+
}
102+
103+
func TestMinioClient_PresignedGetObject(t *testing.T) {
104+
cfg := meta.Config{
105+
Endpoint: "localhost:9000",
106+
AccessKey: "minioadmin",
107+
SecretKey: "minioadmin",
108+
BucketName: "test-bucket",
109+
}
110+
111+
client, err := NewMinioClient(cfg)
112+
if err != nil {
113+
t.Fatalf("Failed to create minio client: %v", err)
114+
}
115+
116+
objectKey := "test-object"
117+
118+
presignedURL, err := client.PresignedGetObject(context.Background(), objectKey, 3600*time.Second)
119+
if err != nil {
120+
t.Fatalf("Failed to get presigned URL: %v", err)
121+
}
122+
123+
t.Logf("Presigned URL for object %s: %s", objectKey, presignedURL)
124+
}
125+
126+
func TestMinioClient_CreateBucket(t *testing.T) {
127+
cfg.SSL = false
128+
129+
client, err := NewMinioClient(cfg)
130+
if err != nil {
131+
t.Fatalf("Failed to create minio client: %v", err)
132+
}
133+
134+
err = client.CreateBucket(context.Background(), "test-bucket")
135+
if err != nil {
136+
t.Fatalf("Failed to create bucket: %v", err)
137+
}
138+
139+
t.Logf("Bucket %s created successfully", "test-bucket")
140+
}
141+
142+
func TestMinioClient_ListObjects(t *testing.T) {
143+
// cfg := meta.Config{
144+
// Endpoint: "localhost:9000",
145+
// AccessKey: "minioadmin",
146+
// SecretKey: "minioadmin",
147+
// BucketName: "test-bucket",
148+
// }
149+
150+
// client, err := NewMinioClient(cfg)
151+
// if err != nil {
152+
// t.Fatalf("Failed to create minio client: %v", err)
153+
// }
154+
155+
// objects, err := client.ListObjects(context.Background(), "", true)
156+
// if err != nil {
157+
// t.Fatalf("Failed to list objects: %v", err)
158+
// }
159+
160+
// t.Logf("Objects in bucket %s: %v", cfg.BucketName, objects)
161+
}
162+
163+
func TestMinioClient_CopyObject(t *testing.T) {
164+
// cfg := meta.Config{
165+
// Endpoint: "localhost:9000",
166+
// AccessKey: "minioadmin",
167+
// SecretKey: "minioadmin",
168+
// BucketName: "test-bucket",
169+
// }
170+
171+
// client, err := NewMinioClient(cfg)
172+
// if err != nil {
173+
// t.Fatalf("Failed to create minio client: %v", err)
174+
// }
175+
176+
// sourceKey := "test-object"
177+
// destinationKey := "test-object-copy"
178+
179+
// err = client.CopyObject(context.Background(), sourceKey, destinationKey)
180+
// if err != nil {
181+
// t.Fatalf("Failed to copy object: %v", err)
182+
// }
183+
184+
// t.Logf("Object %s copied to %s successfully", sourceKey, destinationKey)
185+
}
186+
187+
func TestMinioClient_RemoveBucket(t *testing.T) {
188+
cfg.SSL = false
189+
190+
client, err := NewMinioClient(cfg)
191+
if err != nil {
192+
t.Fatalf("Failed to create minio client: %v", err)
193+
}
194+
195+
err = client.RemoveBucket(context.Background(), "test-bucket")
196+
if err != nil {
197+
t.Fatalf("Failed to remove bucket: %v", err)
198+
}
199+
200+
t.Logf("Bucket %s removed successfully", "test-bucket")
201+
}

components/oss/oss.go

+17-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,21 @@
11
package oss
22

3-
import "context"
3+
import (
4+
"errors"
45

5-
type OSS interface {
6-
UploadFromLocal(ctx context.Context, bucket, filePath, ossPath string) (any, error)
6+
"github.com/alomerry/go-tools/components/oss/meta"
7+
innerMinio "github.com/alomerry/go-tools/components/oss/minio"
8+
)
9+
10+
var (
11+
ErrUnsupportedClientType = errors.New("unsupported client type")
12+
)
13+
14+
func NewClient(cfg meta.Config) (meta.OSSClient, error) {
15+
switch cfg.Type {
16+
case meta.ClientTypeMinio:
17+
return innerMinio.NewMinioClient(cfg)
18+
default:
19+
return nil, ErrUnsupportedClientType
20+
}
721
}

0 commit comments

Comments
 (0)