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