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

Object Storage Service:マルチパートアップロード (Go SDK V1)

最終更新日:Mar 20, 2026

マルチパートアップロードを使用すると、ラージオブジェクトをパートに分割して OSS にアップロードできます。パートを並行してアップロードすることでスループットを向上させ、中断されたアップロードを最初からやり直すことなく再開し、最終的なオブジェクトサイズが不明な場合でもアップロードを開始できます。

前提条件

開始する前に、以下が準備できていることを確認してください。

このトピックの例では、中国 (杭州) リージョンのパブリックエンドポイントを使用します。アプリケーションと OSS バケットが同じリージョンにある場合は、データ転送コストを回避するために内部エンドポイントを使用してください。「リージョンとエンドポイント」を参照してください。

仕組み

マルチパートアップロードには 3 つのステップが必要です。

  1. 初期化Bucket.InitiateMultipartUpload を呼び出します。OSS はグローバルに一意なアップロード ID を返します。

  2. パートのアップロード — 各パートに対して Bucket.UploadPart を呼び出します。パートは、最終的なオブジェクト内での位置を決定するパート番号によって識別されます。同じパート番号で新しいパートをアップロードすると、既存のパートが上書きされます。OSS は、受信した各パートの MD5 ハッシュを ETag ヘッダーで返し、SDK が計算したハッシュと照合して検証します。これらが一致しない場合、OSS は InvalidDigest エラーを返します。

  3. 完了Bucket.CompleteMultipartUpload を呼び出して、アップロードされたすべてのパートを 1 つのオブジェクトにマージします。

オブジェクトのパート単位でのアップロード

次の例では、パートサイズを 5 MiB として、マルチパートアップロードを使用してローカルファイルをアップロードします。

package main

import (
	"fmt"
	"log"
	"os"

	"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("Error: %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("Error: %v", err)
	}

	bucketName := "examplebucket"
	objectName := "exampleobject.txt"
	// ローカルパスが指定されていない場合、ファイルはサンプルプログラムのディレクトリから読み取られます。
	localFilename := "/localpath/exampleobject.txt"

	bucket, err := client.Bucket(bucketName)
	if err != nil {
		log.Fatalf("Error: %v", err)
	}

	// パートサイズを 5 MiB に設定します。
	partSize := int64(5 * 1024 * 1024)

	if err := uploadMultipart(bucket, objectName, localFilename, partSize); err != nil {
		log.Fatalf("Failed to upload multipart: %v", err)
	}
}

func uploadMultipart(bucket *oss.Bucket, objectName, localFilename string, partSize int64) error {
	// 指定されたパートサイズに基づいてローカルファイルをパートに分割します。
	chunks, err := oss.SplitFileByPartSize(localFilename, partSize)
	if err != nil {
		return fmt.Errorf("failed to split file into chunks: %w", err)
	}

	file, err := os.Open(localFilename)
	if err != nil {
		return fmt.Errorf("failed to open file: %w", err)
	}
	defer file.Close()

	// ステップ 1: マルチパートアップロードを初期化します。OSS は一意のアップロード ID を返します。
	imur, err := bucket.InitiateMultipartUpload(objectName)
	if err != nil {
		return fmt.Errorf("failed to initiate multipart upload: %w", err)
	}

	// ステップ 2: 各パートをアップロードします。チャンク番号によって、最終的なオブジェクト内でのパートの位置が決まります。
	var parts []oss.UploadPart
	for _, chunk := range chunks {
		part, err := bucket.UploadPart(imur, file, chunk.Size, chunk.Number)
		if err != nil {
			// アップロードを中止して、すでにアップロードされたパートのストレージを解放します。
			if abortErr := bucket.AbortMultipartUpload(imur); abortErr != nil {
				log.Printf("Failed to abort multipart upload: %v", abortErr)
			}
			return fmt.Errorf("failed to upload part: %w", err)
		}
		parts = append(parts, part)
	}

	// オブジェクト ACL を非公開に設定します。デフォルトでは、オブジェクトはバケット ACL を継承します。
	objectAcl := oss.ObjectACL(oss.ACLPrivate)

	// ステップ 3: アップロードされたすべてのパートをマージして、マルチパートアップロードを完了します。
	_, err = bucket.CompleteMultipartUpload(imur, parts, objectAcl)
	if err != nil {
		if abortErr := bucket.AbortMultipartUpload(imur); abortErr != nil {
			log.Printf("Failed to abort multipart upload: %v", abortErr)
		}
		return fmt.Errorf("failed to complete multipart upload: %w", err)
	}

	log.Printf("Multipart upload completed successfully.")
	return nil
}

よくある質問

マルチパートアップロードを中止する方法

Bucket.AbortMultipartUpload を呼び出してマルチパートアップロードを停止し、それまでにアップロードされたすべてのパートのストレージを解放します。ファイルが破損している、ネットワークが不安定、ストレージ容量が限られている、または誤ってアップロードが開始された場合に、アップロードを中止します。

...
if err = bucket.AbortMultipartUpload(imur); err != nil {
    log.Fatalf("failed to abort multipart upload: %v", err)
}

log.Printf("Multipart upload aborted successfully.")

アップロード済みパートをリスト表示する方法

Bucket.ListUploadedParts を呼び出して、特定のアップロード ID に対して正常にアップロードされたパートを確認します。これは、アップロードの進捗状況のモニタリング、失敗後のリトライ対象パートの特定、またはストレージ使用量の管理に役立ちます。

...
lsRes, err := bucket.ListUploadedParts(imur)
if err != nil {
    log.Fatalf("Failed to list uploaded parts: %v", err)
}

for _, upload := range lsRes.UploadedParts {
    log.Printf("PartNumber: %d, ETag: %s, LastModified: %v\n", upload.PartNumber, upload.ETag, upload.LastModified)
}

バケット内の進行中のすべてのマルチパートアップロードをリスト表示する方法

Bucket.ListMultipartUploads を呼び出して、開始されたがまだ完了または中止されていないすべてのマルチパートアップロードをリスト表示します。これを使用して、バッチアップロードのモニター、停滞したアップロードの検出、またはクリーンアップ対象のアップロードの特定を行います。

以下のパラメーターで、結果をフィルターしたりページ分割したりできます。

パラメーター説明デフォルト
Delimiterデリミタの最初の出現箇所までの共通プレフィックスを共有するオブジェクト名をグループ化します
MaxUploads返すアップロードの最大数1000 (最大値も同じ)
KeyMarkerこの値より辞書順で大きいオブジェクト名を持つアップロードを返します
Prefixオブジェクト名がこのプレフィックスで始まるアップロードのみを返します
UploadIDMarkerKeyMarker と一緒に使用します。同じオブジェクト名で、この値より大きいアップロード ID を持つアップロードを返します。KeyMarker が設定されていない場合は無視されます

デフォルトのパラメーターを使用:

...
lsRes, err := bucket.ListMultipartUploads(oss.KeyMarker(keyMarker), oss.UploadIDMarker(uploadIdMarker))
if err != nil {
    log.Fatalf("failed to list multipart uploads: %v", err)
}

for _, upload := range lsRes.Uploads {
    log.Printf("Key: %s, UploadID: %s\n", upload.Key, upload.UploadID)
}

プレフィックスでフィルター:

...
lsRes, err := bucket.ListMultipartUploads(oss.Prefix("file"))
if err != nil {
    log.Fatalf("failed to list multipart uploads with prefix: %v", err)
}

log.Printf("Uploads: %v", lsRes.Uploads)

結果の数を制限:

...
lsRes, err := bucket.ListMultipartUploads(oss.MaxUploads(100))
if err != nil {
    log.Fatalf("failed to list multipart uploads with limit: %v", err)
}

log.Printf("Uploads: %v", lsRes.Uploads)

プレフィックスと制限を組み合わせる:

...
lsRes, err := bucket.ListMultipartUploads(oss.Prefix("file"), oss.MaxUploads(100))
if err != nil {
    log.Fatalf("failed to list multipart uploads with prefix and limit: %v", err)
}

log.Printf("Uploads: %v", lsRes.Uploads)

次のステップ