すべてのプロダクト
Search
ドキュメントセンター

Object Storage Service:オブジェクトのコピー

最終更新日:Nov 04, 2024

このトピックでは、object Storage Service (OSS) のバージョン管理が有効なバケットにオブジェクトをコピーする方法について説明します。 CopyObjectを呼び出して最大1 GBのサイズのオブジェクトをコピーし、UploadPartCopyを呼び出して1 GBを超えるサイズのオブジェクトをマルチパートコピーを使用してコピーできます。

使用上の注意

  • このトピックでは、中国 (杭州) リージョンのパブリックエンドポイントを使用します。 OSSと同じリージョンにある他のAlibaba CloudサービスからOSSにアクセスする場合は、内部エンドポイントを使用します。 OSSリージョンとエンドポイントの詳細については、「リージョン、エンドポイント、オープンポート」をご参照ください。

  • このトピックでは、アクセス資格情報は環境変数から取得します。 アクセス資格情報の設定方法の詳細については、「アクセス資格情報の設定」をご参照ください。

  • このトピックでは、OSSエンドポイントを使用してOSSClientインスタンスを作成します。 カスタムドメイン名またはSTS (Security Token Service) を使用してOSSClientインスタンスを作成する場合は、「初期化」をご参照ください。

  • オブジェクトをコピーするには、oss:GetObjectおよびoss:PutObject権限が必要です。 詳細については、「RAMユーザーへのカスタムポリシーのアタッチ」をご参照ください。

サンプルコード

小さなオブジェクトをコピーする

CopyObjectを呼び出して、最大1 GBのサイズのオブジェクトをソースバケットから同じリージョン内の宛先バケットにコピーできます。

  • CopyObjectリクエストのx-oss-copy-sourceヘッダーにバージョンIDを指定しない場合、オブジェクトの現在のバージョンがコピーされます。 オブジェクトの現在のバージョンが削除マーカーである場合、OSSはHTTPステータスコード404を返します。 HTTPステータスコードは、オブジェクトが存在しないことを示します。 x-oss-copy-sourceヘッダーにバージョンIDを指定して、特定のオブジェクトバージョンをコピーできます。 削除マーカーはコピーできません。

  • 以前のバージョンのオブジェクトを同じバケットにコピーできます。 コピーされた以前のバージョンがオブジェクトの現在のバージョンになります。 このようにして、オブジェクトの以前のバージョンが復元されます。

  • 宛先バケットのバージョン管理が有効になっている場合、OSSは宛先オブジェクトの一意のバージョンIDを生成します。 バージョンIDは、レスポンスのx-oss-version-idヘッダーの値として返されます。 宛先バケットのバージョン管理が無効または一時停止されている場合、OSSは、宛先オブジェクトのバージョンIDがnullのバージョンを生成し、バージョンIDがnullの以前のバージョンを上書きします。

  • バージョン管理が有効または一時停止されている宛先バケットには、追加可能オブジェクトをコピーできません。

次のサンプルコードは、小さなオブジェクトをコピーする方法の例を示しています。

package main

import (
	"log"
	"net/http"

	"github.com/aliyun/aliyun-oss-go-sdk/oss"
)

func main() {
	// Obtain access credentials from environment variables. Before you run the sample code, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are configured. 
	provider, err := oss.NewEnvironmentVariableCredentialsProvider()
	if err != nil {
		log.Fatalf("Failed to create credentials provider: %v", err)
	}

	// Create an OSSClient instance. 
	// Specify the endpoint of the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the endpoint to https://oss-cn-hangzhou.aliyuncs.com. Specify your actual endpoint. 
	// Specify the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the region to cn-hangzhou. Specify the actual region.
	clientOptions := []oss.ClientOption{oss.SetCredentialsProvider(&provider)}
	clientOptions = append(clientOptions, oss.Region("yourRegion"))
	// Specify the version of the signature algorithm.
	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)
	}

	// Specify the name of the bucket. 
	bucketName := "yourBucketName"
	// Specify the full path of the source object. Do not include the bucket name in the full path. 
	objectName := "yourObjectName"
	// Specify the full path of the destination object. Do not include the bucket name in the full path. 
	destObjectName := "yourDestObjectName"

	// Create a bucket.
	bucket, err := client.Bucket(bucketName)
	if err != nil {
		log.Fatalf("Failed to get bucket '%s': %v", bucketName, err)
	}

	// Copy the specified version of the object to the same bucket and query the version ID of the destination object. 
	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)
	}

	// Display the version information. 
	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リクエストヘッダーにバージョンIDを指定して、既存のオブジェクトの指定されたバージョンからデータをコピーして部品をアップロードする条件を指定できます。 例: x-oss-copy-source: /SourceBucketName/SourceObjectName?versionId=111111

説明

SourceObjectNameパラメーターの値は、URLエンコードされている必要があります。 コピーされたオブジェクトのバージョンIDは、レスポンスのx-oss-copy-source-version-idヘッダーの値として返されます。

リクエストにバージョンIDが指定されておらず、ソースオブジェクトの現在のバージョンが削除マーカーである場合、OSSは404 Not Foundを返します。 リクエストにバージョンIDが指定されており、ソースオブジェクトの指定されたバージョンが削除マーカーである場合、OSSは400 Bad requestを返します。

次のサンプルコードは、ラージオブジェクトをパーツごとにコピーする方法の例を示しています。

package main

import (
	"log"
	"net/http"
	"time"

	"github.com/aliyun/aliyun-oss-go-sdk/oss"
)

func main() {
	// Obtain access credentials from environment variables. Before you run the sample code, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are configured. 
	provider, err := oss.NewEnvironmentVariableCredentialsProvider()
	if err != nil {
		log.Fatalf("Failed to create credentials provider: %v", err)
	}

	// Create an OSSClient instance. 
	// Specify the endpoint of the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the endpoint to https://oss-cn-hangzhou.aliyuncs.com. Specify your actual endpoint. 
	// Specify the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the region to cn-hangzhou. Specify the actual region.
	clientOptions := []oss.ClientOption{oss.SetCredentialsProvider(&provider)}
	clientOptions = append(clientOptions, oss.Region("yourRegion"))
	// Specify the version of the signature algorithm.
	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)
	}

	// Specify the name of the bucket. 
	bucketName := "yourBucketName"
	bucket, err := client.Bucket(bucketName)
	if err != nil {
		log.Fatalf("Failed to get bucket '%s': %v", bucketName, err)
	}

	// Specify the full path of the object. Do not include the bucket name in the full path. 
	objectName := "yourObjectName"
	fileName := "yourFileName"
	futureDate := time.Date(2049, time.January, 10, 23, 0, 0, 0, time.UTC)
	var retHeader http.Header

	// Split the file.
	chunks, err := oss.SplitFileByPartNum(fileName, 3)
	if err != nil {
		log.Fatalf("Failed to split file '%s': %v", fileName, err)
	}

	// Upload a large object as the source object.
	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)
	}

	// Query the version ID of the source object. 
	versionId := oss.GetVersionId(retHeader)
	log.Printf("Source object version ID: %s", versionId)

	// Configure the parameters for the object copy task.
	options := []oss.Option{
		oss.Expires(futureDate),
		oss.Meta("my", "myprop"),
	}

	// Specify the name of the destination object. 
	objectDest := objectName + "dest"
	var parts []oss.UploadPart
	copyOptions := []oss.Option{
		oss.VersionId(versionId),
		oss.GetResponseHeader(&retHeader),
	}

	// Initiate a multipart upload task.
	imu, err := bucket.InitiateMultipartUpload(objectDest, options...)
	if err != nil {
		log.Fatalf("Failed to initiate multipart upload for object '%s': %v", objectDest, err)
	}

	// Copy the large object.
	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)

		// Display the value of the x-oss-copy-source-version-id header. 
		log.Printf("x-oss-copy-source-version-id: %s", oss.GetCopySrcVersionId(retHeader))
	}

	// Complete the multipart upload task.
	_, err = bucket.CompleteMultipartUpload(imu, parts, oss.GetResponseHeader(&retHeader))
	if err != nil {
		log.Fatalf("Failed to complete multipart upload for object '%s': %v", objectDest, err)
	}

	// Display the value of the x-oss-version-id header. 
	log.Printf("x-oss-version-id: %s", oss.GetVersionId(retHeader))
}

関連ドキュメント

  • 小さなオブジェクトをコピーするために呼び出すことができるAPI操作の詳細については、「CopyObject」をご参照ください。

  • ラージオブジェクトをコピーするために呼び出すことができるAPI操作の詳細については、「UploadPartCopy」をご参照ください。