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.2 kB

5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. package storage
  2. import (
  3. "encoding/json"
  4. "encoding/xml"
  5. "path"
  6. "sort"
  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)
  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, complParts string) (string, error){
  105. _, 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. //complParts:{"completedParts":[{"partNumber":2,"eTag":'"684929e7fe8b996d495e7b152d34ae37"'}]}
  114. var parts CompleteParts
  115. err = json.Unmarshal([]byte(complParts), &parts)
  116. if err != nil {
  117. log.Error("json.Unmarshal(%s) failed:(%s)", complParts, err.Error())
  118. return "", err
  119. }
  120. // Complete multipart upload.
  121. var complMultipartUpload completeMultipartUpload
  122. for _,part := range parts.Data {
  123. complMultipartUpload.Parts =append(complMultipartUpload.Parts, miniov6.CompletePart{
  124. PartNumber:part.PartNumber,
  125. ETag:part.ETag,
  126. })
  127. }
  128. // Sort all completed parts.
  129. sort.Sort(completedParts(complMultipartUpload.Parts))
  130. return core.CompleteMultipartUpload(bucketName, objectName, uploadID, complMultipartUpload.Parts)
  131. }