2017-04-25 23 views
0

我需要重命名AWS S3中的一堆對象。對於小物體,以下代碼片段完美地工作:使用MultiPartUpload複製S3對象

input := &s3.CopyObjectInput{ 
    Bucket:  aws.String(bucket), 
    Key:  aws.String(targetPrefix), 
    CopySource: aws.String(source), 
} 
_, err = svc.CopyObject(input) 
if err != nil { 
    panic(errors.Wrap(err, "error copying object")) 
} 

我正在運行S3大小限制爲更大的對象。我知道我需要使用多部分上傳來複制對象。這是我試過到目前爲止:

multiPartUpload, err := svc.CreateMultipartUpload(
    &s3.CreateMultipartUploadInput{ 
     Bucket: aws.String(bucket), 
     Key: aws.String(targetPrefix), // targetPrefix is the new name 
    }, 
) 
if err != nil { 
    panic(errors.Wrap(err, "could not create MultiPartUpload")) 
} 
resp, err := svc.UploadPartCopy(
    &s3.UploadPartCopyInput{ 
     UploadId: multiPartUpload.UploadId, 
     Bucket:  aws.String(bucket), 
     Key:  aws.String(targetPrefix), 
     CopySource: aws.String(source), 
     PartNumber: aws.Int64(1), 
    }, 
) 
if err != nil { 
    panic(errors.Wrap(err, "error copying multipart object")) 
} 
log.Printf("copied: %v", resp) 

的golang SDK撈出上我:

InvalidRequest: The specified copy source is larger than the maximum allowable size for a copy source: 5368709120 

我也曾嘗試以下方法,但我沒有得到這裏列出的任何部分:

multiPartUpload, err := svc.CreateMultipartUpload(
    &s3.CreateMultipartUploadInput{ 
     Bucket: aws.String(bucket), 
     Key: aws.String(targetPrefix), // targetPrefix is the new name 
    }, 
) 
if err != nil { 
    panic(errors.Wrap(err, "could not create MultiPartUpload")) 
} 
err = svc.ListPartsPages(
    &s3.ListPartsInput{ 
     Bucket: aws.String(bucket),  // Required 
     Key:  obj.Key,     // Required 
     UploadId: multiPartUpload.UploadId, // Required 
    }, 
    // Iterate over all parts in the `CopySource` object 
    func(parts *s3.ListPartsOutput, lastPage bool) bool { 
     log.Printf("parts:\n%v\n%v", parts, parts.Parts) 
     // parts.Parts is an empty slice 
     for _, part := range parts.Parts { 
      log.Printf("copying %v part %v", source, part.PartNumber) 
      resp, err := svc.UploadPartCopy(
       &s3.UploadPartCopyInput{ 
        UploadId: multiPartUpload.UploadId, 
        Bucket:  aws.String(bucket), 
        Key:  aws.String(targetPrefix), 
        CopySource: aws.String(source), 
        PartNumber: part.PartNumber, 
       }, 
      ) 
      if err != nil { 
       panic(errors.Wrap(err, "error copying object")) 
      } 
      log.Printf("copied: %v", resp) 
     } 
     return true 
    }, 
) 
if err != nil { 
    panic(errors.Wrap(err, "something went wrong with ListPartsPages!")) 
} 

我在做什麼錯或我誤解了什麼?

回答

2

我認爲ListPartsPages是錯誤的方向,因爲它適用於「多部分上傳」,它是一個不同於s3「對象」的實體。因此,您將已經上傳的部分列入剛創建的分段上傳部分。

您的第一個示例接近您需要的內容,但您需要手動將原始文件拆分爲多個部分,每個部分的範圍由UploadPartCopyInputCopySourceRange指定。至少這是我從閱讀文檔中獲得的。

+0

你是說我需要手動循環並計算'UploadPartCopyInput'中'CopySourceRange'的值嗎?這似乎是可行的,但...繁瑣:( – serverhorror

+0

另外,我倫理上需要upvote和接受,如果這是正確的,但我真的很不喜歡AWS的人如何實施這個SDK?) – serverhorror

+1

我說我認爲它'如果你手動循環,那麼d工作,粗略閱讀api端點不提供任何明顯的選擇。有些令人驚訝的是,他們沒有任何可以抽象出客戶端庫中的細節的東西。一定要加入到's3/s3manager'中... –