You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

minio_ext.go 4.8 kB

5 years ago
4 years ago
5 years ago
4 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
4 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. package storage
  2. import (
  3. "encoding/xml"
  4. "path"
  5. "sort"
  6. "strconv"
  7. "strings"
  8. "sync"
  9. "time"
  10. "code.gitea.io/gitea/modules/log"
  11. "code.gitea.io/gitea/modules/minio_ext"
  12. "code.gitea.io/gitea/modules/setting"
  13. miniov6 "github.com/minio/minio-go/v6"
  14. )
  15. const (
  16. PresignedUploadPartUrlExpireTime = time.Hour * 24 * 7
  17. )
  18. type ComplPart struct {
  19. PartNumber int `json:"partNumber"`
  20. ETag string `json:"eTag"`
  21. }
  22. type CompleteParts struct {
  23. Data []ComplPart `json:"completedParts"`
  24. }
  25. // completedParts is a collection of parts sortable by their part numbers.
  26. // used for sorting the uploaded parts before completing the multipart request.
  27. type completedParts []miniov6.CompletePart
  28. func (a completedParts) Len() int { return len(a) }
  29. func (a completedParts) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
  30. func (a completedParts) Less(i, j int) bool { return a[i].PartNumber < a[j].PartNumber }
  31. // completeMultipartUpload container for completing multipart upload.
  32. type completeMultipartUpload struct {
  33. XMLName xml.Name `xml:"http://s3.amazonaws.com/doc/2006-03-01/ CompleteMultipartUpload" json:"-"`
  34. Parts []miniov6.CompletePart `xml:"Part"`
  35. }
  36. var (
  37. adminClient *minio_ext.Client = nil
  38. coreClient *miniov6.Core = nil
  39. )
  40. var mutex *sync.Mutex
  41. func init() {
  42. mutex = new(sync.Mutex)
  43. }
  44. func getClients() (*minio_ext.Client, *miniov6.Core, error) {
  45. var client *minio_ext.Client
  46. var core *miniov6.Core
  47. mutex.Lock()
  48. defer mutex.Unlock()
  49. if nil != adminClient && nil != coreClient {
  50. client = adminClient
  51. core = coreClient
  52. return client, core, nil
  53. }
  54. var err error
  55. minio := setting.Attachment.Minio
  56. if nil == adminClient {
  57. adminClient, err = minio_ext.New(
  58. minio.Endpoint,
  59. minio.AccessKeyID,
  60. minio.SecretAccessKey,
  61. minio.UseSSL,
  62. )
  63. if nil != err {
  64. return nil, nil, err
  65. }
  66. }
  67. client = adminClient
  68. if nil == coreClient {
  69. coreClient, err = miniov6.NewCore(
  70. minio.Endpoint,
  71. minio.AccessKeyID,
  72. minio.SecretAccessKey,
  73. minio.UseSSL,
  74. )
  75. if nil != err {
  76. return nil, nil, err
  77. }
  78. }
  79. core = coreClient
  80. return client, core, nil
  81. }
  82. func GenMultiPartSignedUrl(uuid string, uploadId string, partNumber int, partSize int64) (string, error) {
  83. minioClient, _, err := getClients()
  84. if err != nil {
  85. log.Error("getClients failed:", err.Error())
  86. return "", err
  87. }
  88. minio := setting.Attachment.Minio
  89. bucketName := minio.Bucket
  90. objectName := strings.TrimPrefix(path.Join(minio.BasePath, path.Join(uuid[0:1], uuid[1:2], uuid)), "/")
  91. return minioClient.GenUploadPartSignedUrl(uploadId, bucketName, objectName, partNumber, partSize, PresignedUploadPartUrlExpireTime, setting.Attachment.Minio.Location)
  92. }
  93. func NewMultiPartUpload(uuid string) (string, error) {
  94. _, core, err := getClients()
  95. if err != nil {
  96. log.Error("getClients failed:", err.Error())
  97. return "", err
  98. }
  99. minio := setting.Attachment.Minio
  100. bucketName := minio.Bucket
  101. objectName := strings.TrimPrefix(path.Join(minio.BasePath, path.Join(uuid[0:1], uuid[1:2], uuid)), "/")
  102. return core.NewMultipartUpload(bucketName, objectName, miniov6.PutObjectOptions{})
  103. }
  104. func CompleteMultiPartUpload(uuid string, uploadID string) (string, error) {
  105. client, core, err := getClients()
  106. if err != nil {
  107. log.Error("getClients failed:", err.Error())
  108. return "", err
  109. }
  110. minio := setting.Attachment.Minio
  111. bucketName := minio.Bucket
  112. objectName := strings.TrimPrefix(path.Join(minio.BasePath, path.Join(uuid[0:1], uuid[1:2], uuid)), "/")
  113. partInfos, err := client.ListObjectParts(bucketName, objectName, uploadID)
  114. if err != nil {
  115. log.Error("ListObjectParts failed:", err.Error())
  116. return "", err
  117. }
  118. var complMultipartUpload completeMultipartUpload
  119. for _, partInfo := range partInfos {
  120. complMultipartUpload.Parts = append(complMultipartUpload.Parts, miniov6.CompletePart{
  121. PartNumber: partInfo.PartNumber,
  122. ETag: partInfo.ETag,
  123. })
  124. }
  125. // Sort all completed parts.
  126. sort.Sort(completedParts(complMultipartUpload.Parts))
  127. return core.CompleteMultipartUpload(bucketName, objectName, uploadID, complMultipartUpload.Parts)
  128. }
  129. func GetPartInfos(uuid string, uploadID string) (string, error) {
  130. minioClient, _, err := getClients()
  131. if err != nil {
  132. log.Error("getClients failed:", err.Error())
  133. return "", err
  134. }
  135. minio := setting.Attachment.Minio
  136. bucketName := minio.Bucket
  137. objectName := strings.TrimPrefix(path.Join(minio.BasePath, path.Join(uuid[0:1], uuid[1:2], uuid)), "/")
  138. partInfos, err := minioClient.ListObjectParts(bucketName, objectName, uploadID)
  139. if err != nil {
  140. log.Error("ListObjectParts failed:", err.Error())
  141. return "", err
  142. }
  143. var chunks string
  144. for _, partInfo := range partInfos {
  145. chunks += strconv.Itoa(partInfo.PartNumber) + "-" + partInfo.ETag + ","
  146. }
  147. return chunks, nil
  148. }