2017-04-25 20 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) 

SDKは、と私にアウトベイルgolang:

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

AWSの人たちがこのSDKをどのように実装したかは本当に嫌いです;) – serverhorror

+1

私は、あなたが手作業でループしていて、apiエンドポイントの読み方が明白な選択肢を提供していない場合は、動作します。しかし、クライアントライブラリの細部を抽象化するものがないというのは驚くべきことです。間違いなく 's3/s3manager'に追加する必要があります... –

関連する問題