分段复制

更新时间: 2019-03-14 10:05

分段复制是分段上传的一种特殊情况,即分段上传任务中的段通过复制OBS指定桶中现有对象(或对象的一部分)来实现。您可以通过ObsClient.CopyPart来复制段。以下代码展示了如何使用分段复制模式复制大对象:

  1. // 引入依赖包
  2. import (
  3. "fmt"
  4. "obs"
  5. )
  6.  
  7. var ak = "*** Provide your Access Key ***"
  8. var sk = "*** Provide your Secret Key ***"
  9. var endpoint = "https://your-endpoint"
  10. var destBucketName = "bucketname"
  11. var destObjectKey = "objectkey"
  12. var sourceBucketName = "sourcebucketname"
  13. var sourceObjectKey = "sourceobjectkey"
  14.  
  15. // 创建ObsClient结构体
  16. var obsClient, _ = obs.New(ak, sk, endpoint)
  17.  
  18. func main() {
  19. // 初始化分段上传任务
  20. input := &obs.InitiateMultipartUploadInput{}
  21. input.Bucket = destBucketName
  22. input.Key = destObjectKey
  23. output, err := obsClient.InitiateMultipartUpload(input)
  24.  
  25. if err != nil {
  26. panic(err)
  27. }
  28.  
  29. uploadId := output.UploadId
  30.  
  31. fmt.Printf("UploadId:%s\n", uploadId)
  32. fmt.Println()
  33.  
  34. // 每段复制100MB
  35. var partSize int64 = 100 * 1024 * 1024
  36.  
  37. // 获取大对象信息
  38. getObjectMetadataInput := &obs.GetObjectMetadataInput{}
  39. getObjectMetadataInput.Bucket = sourceBucketName
  40. getObjectMetadataInput.Key = sourceObjectKey
  41. getObjectMetadataOutput, err := obsClient.GetObjectMetadata(getObjectMetadataInput)
  42.  
  43. if err != nil {
  44. panic(err)
  45. }
  46. objectSize := getObjectMetadataOutput.ContentLength
  47.  
  48. // 计算需要复制的段数
  49. partCount := int(objectSize / partSize)
  50.  
  51. if objectSize%partSize != 0 {
  52. partCount++
  53. }
  54.  
  55. // 执行并发复制段
  56. partChan := make(chan obs.Part, 5)
  57.  
  58. for i := 0; i < partCount; i++ {
  59. partNumber := i + 1
  60. rangeStart := int64(i) * partSize
  61. rangeEnd := rangeStart + partSize - 1
  62. if i+1 == partCount {
  63. rangeEnd = objectSize - 1
  64. }
  65. go func() {
  66. copyPartInput := &obs.CopyPartInput{}
  67. copyPartInput.Bucket = destBucketName
  68. copyPartInput.Key = destObjectKey
  69. copyPartInput.UploadId = uploadId
  70. // 分段号
  71. copyPartInput.PartNumber = int(partNumber)
  72. copyPartInput.CopySourceBucket = sourceBucketName
  73. copyPartInput.CopySourceKey = sourceObjectKey
  74. // 复制段起始位置
  75. copyPartInput.CopySourceRangeStart = rangeStart
  76. // 复制段结束位置
  77. copyPartInput.CopySourceRangeEnd = rangeEnd
  78. copyPartOutput, err := obsClient.CopyPart(copyPartInput)
  79. if err == nil {
  80. fmt.Printf("%d finished\n", partNumber)
  81. partChan <- obs.Part{ETag: copyPartOutput.ETag, PartNumber: copyPartOutput.PartNumber}
  82. } else {
  83. panic(err)
  84. }
  85. }()
  86. }
  87.  
  88. parts := make([]obs.Part, 0, partCount)
  89.  
  90. // 等待复制完成
  91. for {
  92. part, ok := <-partChan
  93. if !ok {
  94. break
  95. }
  96. parts = append(parts, part)
  97.  
  98. if len(parts) == partCount {
  99. close(partChan)
  100. }
  101. }
  102.  
  103. completeMultipartUploadInput := &obs.CompleteMultipartUploadInput{}
  104. completeMultipartUploadInput.Bucket = destBucketName
  105. completeMultipartUploadInput.Key = destObjectKey
  106. completeMultipartUploadInput.UploadId = uploadId
  107. completeMultipartUploadInput.Parts = parts
  108. // 合并段
  109. completeMultipartUploadOutput, err := obsClient.CompleteMultipartUpload(completeMultipartUploadInput)
  110. if err != nil {
  111. panic(err)
  112. }
  113. fmt.Printf("RequestId:%s\n", completeMultipartUploadOutput.RequestId)
  114. }

父主题:上传对象