1
+ package golang
2
+
3
+ import (
4
+ "bytes"
5
+ "context"
6
+ "fmt"
7
+ "io"
8
+ "os"
9
+ "path/filepath"
10
+ "strconv"
11
+ "strings"
12
+
13
+ "github.com/google/uuid"
14
+ "github.com/minio/minio-go/v7"
15
+ "github.com/minio/minio-go/v7/pkg/credentials"
16
+ )
17
+
18
+ type Storage struct {
19
+ client * minio.Client
20
+ }
21
+
22
+ var instance * Storage
23
+
24
+ func UniqueName (name string ) string {
25
+ ext := filepath .Ext (name )
26
+ basename := name [:len (name )- len (ext )]
27
+ uuidStr := strings .Split (uuid .New ().String (), "-" )[0 ]
28
+ return fmt .Sprintf ("%s.%s%s" , basename , uuidStr , ext )
29
+ }
30
+
31
+ func NewStorage () (* Storage , error ) {
32
+ address , exists := os .LookupEnv ("MINIO_ADDRESS" )
33
+ if ! exists {
34
+ return nil , nil
35
+ }
36
+
37
+ accessKey := os .Getenv ("MINIO_ACCESS_KEY" )
38
+ secretKey := os .Getenv ("MINIO_SECRET_KEY" )
39
+
40
+ parts := strings .Split (address , ":" )
41
+ endpoint := parts [0 ]
42
+ var port int = 9000 // Default port
43
+
44
+ if len (parts ) > 1 {
45
+ var err error
46
+ port , err = strconv .Atoi (parts [1 ])
47
+ if err != nil {
48
+ return nil , fmt .Errorf ("invalid port in MINIO_ADDRESS: %v" , err )
49
+ }
50
+ }
51
+
52
+ client , err := minio .New (endpoint , & minio.Options {
53
+ Creds : credentials .NewStaticV4 (accessKey , secretKey , "" ),
54
+ Secure : false ,
55
+ Port : uint16 (port ),
56
+ })
57
+ if err != nil {
58
+ return nil , err
59
+ }
60
+
61
+ return & Storage {client : client }, nil
62
+ }
63
+
64
+ func (s * Storage ) Upload (bucket , file , filepath string ) (string , error ) {
65
+ keyName := UniqueName (file )
66
+ _ , err := s .client .FPutObject (context .Background (), bucket , keyName , filepath , minio.PutObjectOptions {})
67
+ if err != nil {
68
+ return "" , err
69
+ }
70
+ return keyName , nil
71
+ }
72
+
73
+ func (s * Storage ) Download (bucket , file , filepath string ) error {
74
+ return s .client .FGetObject (context .Background (), bucket , file , filepath , minio.GetObjectOptions {})
75
+ }
76
+
77
+ func (s * Storage ) DownloadDirectory (bucket , prefix , path string ) error {
78
+ ctx := context .Background ()
79
+ objects := s .client .ListObjects (ctx , bucket , minio.ListObjectsOptions {
80
+ Prefix : prefix ,
81
+ Recursive : true ,
82
+ })
83
+
84
+ for object := range objects {
85
+ if object .Err != nil {
86
+ return object .Err
87
+ }
88
+
89
+ objectPath := filepath .Join (path , object .Key )
90
+ if err := os .MkdirAll (filepath .Dir (objectPath ), 0755 ); err != nil {
91
+ return err
92
+ }
93
+
94
+ if err := s .Download (bucket , object .Key , objectPath ); err != nil {
95
+ return err
96
+ }
97
+ }
98
+
99
+ return nil
100
+ }
101
+
102
+ func (s * Storage ) UploadStream (bucket , file string , data []byte ) (string , error ) {
103
+ keyName := UniqueName (file )
104
+ reader := bytes .NewReader (data )
105
+ _ , err := s .client .PutObject (context .Background (), bucket , keyName , reader , int64 (len (data )), minio.PutObjectOptions {})
106
+ if err != nil {
107
+ return "" , err
108
+ }
109
+ return keyName , nil
110
+ }
111
+
112
+ func (s * Storage ) DownloadStream (bucket , file string ) ([]byte , error ) {
113
+ obj , err := s .client .GetObject (context .Background (), bucket , file , minio.GetObjectOptions {})
114
+ if err != nil {
115
+ return nil , err
116
+ }
117
+ defer obj .Close ()
118
+
119
+ return io .ReadAll (obj )
120
+ }
121
+
122
+ func GetInstance () (* Storage , error ) {
123
+ if instance == nil {
124
+ var err error
125
+ instance , err = NewStorage ()
126
+ if err != nil {
127
+ return nil , err
128
+ }
129
+ }
130
+ return instance , nil
131
+ }
0 commit comments