minio.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. package minio
  2. import (
  3. "bytes"
  4. "context"
  5. "encoding/base64"
  6. "errors"
  7. "github.com/minio/minio-go"
  8. "io"
  9. "io/ioutil"
  10. "net/http"
  11. "strings"
  12. "sync"
  13. )
  14. var (
  15. internalClient *Client
  16. once sync.Once
  17. )
  18. // ErrorInvalidName 无效的文件名
  19. var ErrorInvalidName = errors.New("invalid file name")
  20. // Init 初始化minio客户端
  21. func Init(addr, accessKey, secretKey string) *Client {
  22. once.Do(func() {
  23. cli, err := minio.New(addr, accessKey, secretKey, false)
  24. if err != nil {
  25. panic(err)
  26. }
  27. internalClient = &Client{cli}
  28. })
  29. return internalClient
  30. }
  31. // GetClient 获取文件存储客户端
  32. func GetClient() *Client {
  33. return internalClient
  34. }
  35. // Client minio客户端
  36. type Client struct {
  37. cli *minio.Client
  38. }
  39. // MinioClient 文件存储客户端
  40. func (a *Client) MinioClient() *minio.Client {
  41. return a.cli
  42. }
  43. // Store 保存文件
  44. // filename 前3段约束(第一段约束为(前缀),第二段为bucket(业务类型),第三段以后为文件key)
  45. func (a *Client) Store(ctx context.Context, filename string, data io.Reader, size int64) error {
  46. if ctx == nil {
  47. ctx = context.Background()
  48. }
  49. bucket, objName, err := a.parseFilename(filename)
  50. if err != nil {
  51. return err
  52. }
  53. exists, err := a.cli.BucketExists(bucket)
  54. if err != nil {
  55. return err
  56. } else if !exists {
  57. err = a.cli.MakeBucket(bucket, "local")
  58. if err != nil {
  59. return err
  60. }
  61. }
  62. buf, err := ioutil.ReadAll(data)
  63. if err != nil {
  64. return err
  65. }
  66. rd := bytes.NewBuffer(buf)
  67. if size == 0 {
  68. size = int64(rd.Len())
  69. }
  70. _, err = a.cli.PutObjectWithContext(ctx, bucket, objName, rd, size, minio.PutObjectOptions{
  71. ContentType: http.DetectContentType(buf),
  72. NumThreads: 2,
  73. })
  74. return err
  75. }
  76. // 解析文件名
  77. func (a *Client) parseFilename(filename string) (string, string, error) {
  78. if len(filename) > 0 && filename[0] == '/' {
  79. filename = filename[1:]
  80. }
  81. names := strings.Split(filename, "/")
  82. if len(names) < 3 {
  83. return "", "", ErrorInvalidName
  84. }
  85. return strings.ToLower(names[1]), strings.Join(names[2:], "/"), nil
  86. }
  87. // Get 获取文件对象
  88. func (a *Client) Get(ctx context.Context, filename string) (*minio.Object, error) {
  89. if ctx == nil {
  90. ctx = context.Background()
  91. }
  92. bucketName, objectName, err := a.parseFilename(filename)
  93. if err != nil {
  94. return nil, err
  95. }
  96. return a.cli.GetObjectWithContext(ctx, bucketName, objectName, minio.GetObjectOptions{})
  97. }
  98. // Stat 文件状态信息
  99. func (a *Client) Stat(filename string) (minio.ObjectInfo, error) {
  100. bucketName, objectName, err := a.parseFilename(filename)
  101. if err != nil {
  102. return minio.ObjectInfo{}, err
  103. }
  104. return a.cli.StatObject(bucketName, objectName, minio.StatObjectOptions{})
  105. }
  106. // GetBase64 获取文件的base64数据
  107. func (a *Client) GetBase64(ctx context.Context, filename string) (string, error) {
  108. obj, err := a.Get(ctx, filename)
  109. if err != nil {
  110. return "", err
  111. }
  112. defer obj.Close()
  113. buf, err := ioutil.ReadAll(obj)
  114. if err != nil {
  115. return "", err
  116. }
  117. s := base64.StdEncoding.EncodeToString(buf)
  118. return s, nil
  119. }