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.

multipart.go 5.0 kB

1 year ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. package ops2
  2. /*
  3. import (
  4. "fmt"
  5. "gitlink.org.cn/cloudream/common/pkgs/ioswitch/dag"
  6. "gitlink.org.cn/cloudream/common/pkgs/ioswitch/exec"
  7. log "gitlink.org.cn/cloudream/common/pkgs/logger"
  8. cdssdk "gitlink.org.cn/cloudream/common/sdks/storage"
  9. "gitlink.org.cn/cloudream/storage/common/pkgs/storage/cos"
  10. "gitlink.org.cn/cloudream/storage/common/pkgs/storage/mgr"
  11. "gitlink.org.cn/cloudream/storage/common/pkgs/storage/obs"
  12. "gitlink.org.cn/cloudream/storage/common/pkgs/storage/oss"
  13. "gitlink.org.cn/cloudream/storage/common/pkgs/storage/types"
  14. "io"
  15. "time"
  16. )
  17. func init() {
  18. exec.UseOp[*MultipartManage]()
  19. exec.UseOp[*MultipartUpload]()
  20. exec.UseVarValue[*InitUploadValue]()
  21. }
  22. type InitUploadValue struct {
  23. Key string `xml:"Key"` // Object name to upload
  24. UploadID string `xml:"UploadId"` // Generated UploadId
  25. }
  26. func (v *InitUploadValue) Clone() exec.VarValue {
  27. return &*v
  28. }
  29. type MultipartManage struct {
  30. Address cdssdk.StorageAddress `json:"address"`
  31. UploadArgs exec.VarID `json:"uploadArgs"`
  32. UploadOutput exec.VarID `json:"uploadOutput"`
  33. StorageID cdssdk.StorageID `json:"storageID"`
  34. }
  35. func (o *MultipartManage) Execute(ctx *exec.ExecContext, e *exec.Executor) error {
  36. manager, err := exec.GetValueByType[*mgr.Manager](ctx)
  37. if err != nil {
  38. return err
  39. }
  40. var client types.MultipartUploader
  41. switch addr := o.Address.(type) {
  42. case *cdssdk.OSSAddress:
  43. client = oss.NewMultiPartUpload(addr)
  44. case *cdssdk.OBSAddress:
  45. client = obs.NewMultiPartUpload(addr)
  46. case *cdssdk.COSAddress:
  47. client = cos.NewMultiPartUpload(addr)
  48. }
  49. defer client.Close()
  50. tempStore, err := manager.GetTempStore(o.StorageID)
  51. if err != nil {
  52. return err
  53. }
  54. objName := tempStore.CreateTemp()
  55. uploadID, err := client.InitiateMultipartUpload(objName)
  56. if err != nil {
  57. return err
  58. }
  59. e.PutVar(o.UploadArgs, &InitUploadValue{
  60. UploadID: uploadID,
  61. Key: objName,
  62. })
  63. parts, err := exec.BindVar[*UploadPartOutputValue](e, ctx.Context, o.UploadOutput)
  64. if err != nil {
  65. return err
  66. }
  67. err = client.CompleteMultipartUpload(uploadID, objName, parts.Parts)
  68. if err != nil {
  69. return err
  70. }
  71. return nil
  72. }
  73. func (o *MultipartManage) String() string {
  74. return "MultipartManage"
  75. }
  76. type MultipartManageNode struct {
  77. dag.NodeBase
  78. Address cdssdk.StorageAddress
  79. StorageID cdssdk.StorageID `json:"storageID"`
  80. }
  81. func (b *GraphNodeBuilder) NewMultipartManage(addr cdssdk.StorageAddress, storageID cdssdk.StorageID) *MultipartManageNode {
  82. node := &MultipartManageNode{
  83. Address: addr,
  84. StorageID: storageID,
  85. }
  86. b.AddNode(node)
  87. return node
  88. }
  89. func (t *MultipartManageNode) GenerateOp() (exec.Op, error) {
  90. return &MultipartManage{
  91. Address: t.Address,
  92. StorageID: t.StorageID,
  93. }, nil
  94. }
  95. type MultipartUpload struct {
  96. Address cdssdk.StorageAddress `json:"address"`
  97. UploadArgs exec.VarID `json:"uploadArgs"`
  98. UploadOutput exec.VarID `json:"uploadOutput"`
  99. PartNumbers []int `json:"partNumbers"`
  100. PartSize []int64 `json:"partSize"`
  101. Input exec.VarID `json:"input"`
  102. }
  103. type UploadPartOutputValue struct {
  104. Parts []*types.UploadPartOutput `json:"parts"`
  105. }
  106. func (v *UploadPartOutputValue) Clone() exec.VarValue {
  107. return &*v
  108. }
  109. func (o *MultipartUpload) Execute(ctx *exec.ExecContext, e *exec.Executor) error {
  110. initUploadResult, err := exec.BindVar[*InitUploadValue](e, ctx.Context, o.UploadArgs)
  111. if err == nil {
  112. return err
  113. }
  114. input, err := exec.BindVar[*exec.StreamValue](e, ctx.Context, o.Input)
  115. if err != nil {
  116. return err
  117. }
  118. defer input.Stream.Close()
  119. var client types.MultipartUploader
  120. switch addr := o.Address.(type) {
  121. case *cdssdk.OSSAddress:
  122. client = oss.NewMultiPartUpload(addr)
  123. }
  124. var parts UploadPartOutputValue
  125. for i := 0; i < len(o.PartNumbers); i++ {
  126. startTime := time.Now()
  127. uploadPart, err := client.UploadPart(initUploadResult.UploadID, initUploadResult.Key, o.PartSize[i], o.PartNumbers[i], io.LimitReader(input.Stream, o.PartSize[i]))
  128. log.Debugf("upload multipart spend time: %v", time.Since(startTime))
  129. if err != nil {
  130. return fmt.Errorf("failed to upload part: %w", err)
  131. }
  132. parts.Parts = append(parts.Parts, uploadPart)
  133. }
  134. e.PutVar(o.UploadOutput, &parts)
  135. return nil
  136. }
  137. func (o *MultipartUpload) String() string {
  138. return "MultipartUpload"
  139. }
  140. type MultipartUploadNode struct {
  141. dag.NodeBase
  142. Address cdssdk.StorageAddress
  143. PartNumbers []int `json:"partNumbers"`
  144. PartSize []int64 `json:"partSize"`
  145. }
  146. func (b *GraphNodeBuilder) NewMultipartUpload(addr cdssdk.StorageAddress, partNumbers []int, partSize []int64) *MultipartUploadNode {
  147. node := &MultipartUploadNode{
  148. Address: addr,
  149. PartNumbers: partNumbers,
  150. PartSize: partSize,
  151. }
  152. b.AddNode(node)
  153. return node
  154. }
  155. func (t MultipartUploadNode) GenerateOp() (exec.Op, error) {
  156. return &MultipartUpload{
  157. Address: t.Address,
  158. PartNumbers: t.PartNumbers,
  159. PartSize: t.PartSize,
  160. }, nil
  161. }
  162. */

本项目旨在将云际存储公共基础设施化,使个人及企业可低门槛使用高效的云际存储服务(安装开箱即用云际存储客户端即可,无需关注其他组件的部署),同时支持用户灵活便捷定制云际存储的功能细节。