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

5 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  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 = int64(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(bucketName string, objectName 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. return minioClient.GenUploadPartSignedUrl(uploadId, bucketName, objectName, partNumber, partSize, PresignedUploadPartUrlExpireTime)
  89. }
  90. func NewMultiPartUpload(uuid string) (string, error){
  91. _, core, err := getClients()
  92. if err != nil {
  93. log.Error("getClients failed:", err.Error())
  94. return "", err
  95. }
  96. minio := setting.Attachment.Minio
  97. bucketName := minio.Bucket
  98. objectName := strings.TrimPrefix(path.Join(minio.BasePath, path.Join(uuid[0:1], uuid[1:2], uuid)), "/")
  99. return core.NewMultipartUpload(bucketName, objectName, miniov6.PutObjectOptions{})
  100. }
  101. func CompleteMultiPartUpload(uuid string, uploadID string, complParts string) (string, error){
  102. _, core, err := getClients()
  103. if err != nil {
  104. log.Error("getClients failed:", err.Error())
  105. return "", err
  106. }
  107. minio := setting.Attachment.Minio
  108. bucketName := minio.Bucket
  109. objectName := strings.TrimPrefix(path.Join(minio.BasePath, path.Join(uuid[0:1], uuid[1:2], uuid)), "/")
  110. //complParts:{"completedParts":[{"partNumber":2,"eTag":'"684929e7fe8b996d495e7b152d34ae37"'}]}
  111. var parts CompleteParts
  112. err = json.Unmarshal([]byte(complParts), &parts)
  113. if err != nil {
  114. log.Error("json.Unmarshal(%s) failed:(%s)", complParts, err.Error())
  115. return "", err
  116. }
  117. // Complete multipart upload.
  118. var complMultipartUpload completeMultipartUpload
  119. for _,part := range parts.Data {
  120. complMultipartUpload.Parts =append(complMultipartUpload.Parts, miniov6.CompletePart{
  121. PartNumber:part.PartNumber,
  122. ETag:part.ETag,
  123. })
  124. }
  125. // Sort all completed parts.
  126. sort.Sort(completedParts(complMultipartUpload.Parts))
  127. return core.CompleteMultipartUpload(bucketName, objectName, uploadID, complMultipartUpload.Parts)
  128. }