このトピックでは、バージョン管理が有効なバケット内のオブジェクトをコピーする方法について説明します。1 GB 未満のオブジェクトは CopyObject メソッドを使用してコピーできます。1 GB を超えるオブジェクトは、マルチパートコピーメソッド (UploadPartCopy) を使用してコピーできます。
注意事項
このトピックでは、中国 (杭州) リージョンのパブリックエンドポイントを使用します。OSS と同じリージョンにある他の Alibaba Cloud サービスから OSS にアクセスする場合は、内部エンドポイントを使用してください。OSS のリージョンとエンドポイントの詳細については、「リージョンとエンドポイント」をご参照ください。
このトピックでは、アクセス認証情報は環境変数から取得されます。アクセス認証情報の設定方法の詳細については、「アクセス認証情報の設定」をご参照ください。
このトピックでは、OSS エンドポイントを使用して OSSClient インスタンスを作成します。カスタムドメイン名または Security Token Service (STS) を使用して OSSClient インスタンスを作成する場合は、「クライアントの設定 (Go SDK V1)」をご参照ください。
オブジェクトをコピーするには、
oss:GetObjectおよびoss:PutObject権限が必要です。詳細については、「RAM ユーザーへのカスタムポリシーのアタッチ」をご参照ください。
サンプルコード
小さいオブジェクトのコピー
1 GB 未満のオブジェクトの場合、CopyObject メソッドを使用して、同じリージョン内のソースバケットから宛先バケットにオブジェクトをコピーできます。
デフォルトでは、x-oss-copy-source はオブジェクトの現在のバージョンをコピーします。現在のバージョンが削除マーカーの場合、OSS は 404 Not Found エラーを返します。x-oss-copy-source に versionId を追加して、オブジェクトの特定のバージョンをコピーできます。削除マーカーはコピーできません。
オブジェクトの以前のバージョンを同じバケットにコピーできます。この操作により、オブジェクトの新しい現在のバージョンが作成され、オブジェクトが以前の状態に復元されます。
宛先バケットでバージョン管理が有効になっている場合、OSS はコピーされたオブジェクトの一意の versionId を自動的に生成します。この versionId は x-oss-version-id レスポンスヘッダーで返されます。宛先バケットでバージョン管理が有効になっていないか、一時停止されている場合、OSS は versionId が "null" のバージョンを新しいオブジェクトに対して生成します。この新しいバージョンは、versionId が "null" の既存のバージョンを上書きします。
バージョン管理が有効または一時停止されている宛先バケットに、追加可能オブジェクトをコピーすることはできません。
次のコードは、小さいオブジェクトをコピーする方法を示しています。
package main
import (
"log"
"net/http"
"github.com/aliyun/aliyun-oss-go-sdk/oss"
)
func main() {
// 環境変数からアクセス認証情報を取得します。サンプルコードを実行する前に、環境変数 OSS_ACCESS_KEY_ID および OSS_ACCESS_KEY_SECRET が設定されていることを確認してください。
provider, err := oss.NewEnvironmentVariableCredentialsProvider()
if err != nil {
log.Fatalf("Failed to create credentials provider: %v", err)
}
// OSSClient インスタンスを作成します。
// yourEndpoint をバケットのエンドポイントに設定します。たとえば、中国 (杭州) リージョンの場合、エンドポイントを https://oss-cn-hangzhou.aliyuncs.com に設定します。他のリージョンについては、実際のエンドポイントを使用してください。
// yourRegion をバケットが配置されているリージョンに設定します。たとえば、中国 (杭州) リージョンの場合、リージョンを cn-hangzhou に設定します。他のリージョンについては、実際のリージョンを使用してください。
clientOptions := []oss.ClientOption{oss.SetCredentialsProvider(&provider)}
clientOptions = append(clientOptions, oss.Region("yourRegion"))
// 署名バージョンを設定します。
clientOptions = append(clientOptions, oss.AuthVersion(oss.AuthV4))
client, err := oss.New("yourEndpoint", "", "", clientOptions...)
if err != nil {
log.Fatalf("Failed to create OSS client: %v", err)
}
// yourBucketName をバケットの名前に設定します。
bucketName := "yourBucketName"
// yourObjectName をソースオブジェクトの完全なパス (バケット名を除く) に設定します。
objectName := "yourObjectName"
// yourDestObjectName を宛先オブジェクトの完全なパス (バケット名を除く) に設定します。
destObjectName := "yourDestObjectName"
// バケットインスタンスを取得します。
bucket, err := client.Bucket(bucketName)
if err != nil {
log.Fatalf("Failed to get bucket '%s': %v", bucketName, err)
}
// オブジェクトの特定のバージョンを同じバケット内の別のオブジェクトにコピーし、バージョン情報を取得します。
var retHeader http.Header
_, err = bucket.CopyObject(objectName, destObjectName, oss.VersionId("yourObjectVersionId"), oss.GetResponseHeader(&retHeader))
if err != nil {
log.Fatalf("Failed to copy object '%s' to '%s': %v", objectName, destObjectName, err)
}
// バージョン情報を出力します。
versionId := oss.GetVersionId(retHeader)
copySourceVersionId := oss.GetCopySrcVersionId(retHeader)
log.Printf("x-oss-version-id: %s", versionId)
log.Printf("x-oss-copy-source-version-id: %s", copySourceVersionId)
}
大きいオブジェクトのコピー
1 GB を超えるオブジェクトの場合、マルチパートコピー (UploadPartCopy) を使用できます。
デフォルトでは、UploadPartCopy 操作は、既存のオブジェクトの現在のバージョンからデータをコピーしてパートをアップロードします。x-oss-copy-source リクエストヘッダーに versionId サブリソースを含めることで、オブジェクトの特定のバージョンをコピーできます。例:x-oss-copy-source: /SourceBucketName/SourceObjectName?versionId=111111。
SourceObjectName は URL エンコードされている必要があります。レスポンスは、ソースオブジェクトのバージョン ID を x-oss-copy-source-version-id で返します。
versionId を指定せず、オブジェクトの現在のバージョンが削除マーカーである場合、OSS は 404 Not Found エラーを返します。versionId を指定して削除マーカーをコピーしようとすると、OSS は 400 Bad Request エラーを返します。
次のコードは、マルチパートコピーを実行する方法を示しています。
package main
import (
"log"
"net/http"
"time"
"github.com/aliyun/aliyun-oss-go-sdk/oss"
)
func main() {
// 環境変数からアクセス認証情報を取得します。サンプルコードを実行する前に、環境変数 OSS_ACCESS_KEY_ID および OSS_ACCESS_KEY_SECRET が設定されていることを確認してください。
provider, err := oss.NewEnvironmentVariableCredentialsProvider()
if err != nil {
log.Fatalf("Failed to create credentials provider: %v", err)
}
// OSSClient インスタンスを作成します。
// yourEndpoint をバケットのエンドポイントに設定します。たとえば、中国 (杭州) リージョンの場合、エンドポイントを https://oss-cn-hangzhou.aliyuncs.com に設定します。他のリージョンについては、実際のエンドポイントを使用してください。
// yourRegion をバケットが配置されているリージョンに設定します。たとえば、中国 (杭州) リージョンの場合、リージョンを cn-hangzhou に設定します。他のリージョンについては、実際のリージョンを使用してください。
clientOptions := []oss.ClientOption{oss.SetCredentialsProvider(&provider)}
clientOptions = append(clientOptions, oss.Region("yourRegion"))
// 署名バージョンを設定します。
clientOptions = append(clientOptions, oss.AuthVersion(oss.AuthV4))
client, err := oss.New("yourEndpoint", "", "", clientOptions...)
if err != nil {
log.Fatalf("Failed to create OSS client: %v", err)
}
// yourBucketName をバケットの名前に設定します。
bucketName := "yourBucketName"
bucket, err := client.Bucket(bucketName)
if err != nil {
log.Fatalf("Failed to get bucket '%s': %v", bucketName, err)
}
// yourObjectName をオブジェクトの完全なパス (バケット名を除く) に設定します。
objectName := "yourObjectName"
fileName := "yourFileName"
futureDate := time.Date(2049, time.January, 10, 23, 0, 0, 0, time.UTC)
var retHeader http.Header
// ファイルを分割します。
chunks, err := oss.SplitFileByPartNum(fileName, 3)
if err != nil {
log.Fatalf("Failed to split file '%s': %v", fileName, err)
}
// コピーする大きいファイルをアップロードします。
err = bucket.PutObjectFromFile(objectName, fileName, oss.GetResponseHeader(&retHeader))
if err != nil {
log.Fatalf("Failed to put object '%s' from file '%s': %v", objectName, fileName, err)
}
// アップロードされたソースファイルの versionId を取得します。
versionId := oss.GetVersionId(retHeader)
log.Printf("Source object version ID: %s", versionId)
// コピー操作のパラメーターを設定します。
options := []oss.Option{
oss.Expires(futureDate),
oss.Meta("my", "myprop"),
}
// 宛先オブジェクト名。
objectDest := objectName + "dest"
var parts []oss.UploadPart
copyOptions := []oss.Option{
oss.VersionId(versionId),
oss.GetResponseHeader(&retHeader),
}
// マルチパートアップロードイベントを初期化します。
imu, err := bucket.InitiateMultipartUpload(objectDest, options...)
if err != nil {
log.Fatalf("Failed to initiate multipart upload for object '%s': %v", objectDest, err)
}
// 大きいファイルのコピーを実行します。
for _, chunk := range chunks {
part, err := bucket.UploadPartCopy(imu, bucketName, objectName, chunk.Offset, chunk.Size, int(chunk.Number), copyOptions...)
if err != nil {
log.Fatalf("Failed to upload part %d of object '%s': %v", chunk.Number, objectName, err)
}
parts = append(parts, part)
// x-oss-copy-source-version-id を出力します。
log.Printf("x-oss-copy-source-version-id: %s", oss.GetCopySrcVersionId(retHeader))
}
// マルチパートアップロードを完了します。
_, err = bucket.CompleteMultipartUpload(imu, parts, oss.GetResponseHeader(&retHeader))
if err != nil {
log.Fatalf("Failed to complete multipart upload for object '%s': %v", objectDest, err)
}
// x-oss-version-id を出力します。
log.Printf("x-oss-version-id: %s", oss.GetVersionId(retHeader))
}
関連ドキュメント
小さいオブジェクトをコピーするための API 操作の詳細については、「CopyObject」をご参照ください。
大きいオブジェクトをコピーするための API 操作の詳細については、「UploadPartCopy」をご参照ください。