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

Object Storage Service:オブジェクトのコピー (Go SDK V1)

最終更新日:Nov 29, 2025

このトピックでは、バージョン管理が有効なバケット内のオブジェクトをコピーする方法について説明します。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」をご参照ください。