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

Object Storage Service:追加アップロード

最終更新日:Jul 05, 2025

既存の追加可能なオブジェクトにコンテンツを追加できます。このトピックでは、Object Storage Service (OSS) SDK for Go 2.0 を使用して追加アップロードを実行する方法について説明します。

使用上の注意

  • このトピックのサンプルコードでは、中国 (杭州) リージョンのリージョン ID cn-hangzhou を使用しています。デフォルトでは、パブリックエンドポイントを使用してバケット内のリソースにアクセスします。バケットが配置されているのと同じリージョン内の他の Alibaba Cloud サービスを使用してバケット内のリソースにアクセスする場合は、内部エンドポイントを使用します。 OSS のリージョンとエンドポイントの詳細については、「リージョンとエンドポイント」をご参照ください。

  • このトピックでは、アクセス認証情報は環境変数から取得されます。アクセス認証情報を構成する方法の詳細については、「アクセス認証情報を構成する」をご参照ください。

  • コンテンツを追加するオブジェクトが存在しない場合は、追加アップロード操作を呼び出すと、追加可能なオブジェクトが作成されます。

  • コンテンツを追加するオブジェクトが既に存在する場合:

    • オブジェクトが追加可能なオブジェクトであり、追加操作の開始位置として指定された位置が現在のオブジェクトの長さと等しい場合、オブジェクトはオブジェクトの末尾に追加されます。

    • オブジェクトが追加可能なオブジェクトであり、追加操作の開始位置として指定された位置が現在のオブジェクトの長さと等しくない場合、PositionNotEqualToLength エラーが返されます。

    • オブジェクトが追加可能なオブジェクトでない場合、ObjectNotAppendable エラーが返されます。

権限

デフォルトでは、Alibaba Cloud アカウントにはフルパーミッションがあります。Alibaba Cloud アカウントの RAM ユーザーまたは RAM ロールには、デフォルトではパーミッションがありません。Alibaba Cloud アカウントまたはアカウント管理者は、RAM ポリシーまたはバケットポリシーを通じて操作パーミッションを付与する必要があります。

API

アクション

定義

AppendObject

oss:PutObject

この操作を呼び出して、既存のオブジェクトにオブジェクトを追加することでオブジェクトをアップロードできます。

oss:PutObjectTagging

既存のオブジェクトにオブジェクトを追加してアップロードする場合、x-oss-tagging を介してオブジェクトタグを指定すると、このパーミッションが必要になります。

メソッド

OSS SDK for Go 2.0 は、AppendFile 操作を提供して、バケット内のオブジェクトに対する読み取りおよび書き込み操作をシミュレートします。次の表に、AppendFile 操作と AppendObject 操作について説明します。

操作

説明

Client.AppendObject

追加アップロードを実行して、最大 5 GiB のオブジェクトをアップロードします。

CRC-64 をサポートします(デフォルトで有効)。

アップロードタスクの進捗状況をプログレスバーに表示します。

タイプが io.Reader のリクエストボディをサポートします。リクエストボディのタイプが io.Seeker の場合、アップロードタスクが失敗すると、オブジェクトは再アップロードされます。この操作は冪等であり、オブジェクトの再アップロードは失敗する可能性があります。

Client.AppendFile

Client.AppendObject と同じ機能を提供します。

オブジェクトの再アップロードが失敗した後のフォールトトレランスを最適化します。

AppendOnlyFile 操作を含みます。

AppendOnlyFile.Write

AppendOnlyFile.WriteFrom

追加アップロードの高度な操作:AppendFile

AppendFile 操作を呼び出して、既存のオブジェクトにデータを追加することでデータをアップロードできます。オブジェクトが存在しない場合、AppendFile 操作は追加可能なオブジェクトを作成します。オブジェクトが存在するが追加可能なタイプでない場合、エラーが返されます。

次のサンプルコードは、AppendFile 操作を定義しています。

type AppendOnlyFile struct {
... // コードは省略されています
}

func (c *Client) AppendFile(ctx context.Context, bucket string, key string, optFns ...func(*AppendOptions)) (*AppendOnlyFile, error)

リクエストパラメーター

パラメーター

タイプ

説明

ctx

context.Context

リクエストのコンテキスト。

bucket

string

バケットの名前。

key

string

オブジェクトの名前。

optFns

...func(*AppendOptions)

オプション。データを追加するときに構成できるオプション。

AppendOptions のオプション

オプション

タイプ

説明

RequestPayer

*string

リクエストごとの支払い が有効になっている場合、RequestPayer を requester に設定する必要があります。

CreateParameter

*AppendObjectRequest

オブジェクトを初めてアップロードするときに指定するオブジェクトメタデータ。オブジェクトのコンテンツタイプ、メタデータ、アクセス制御リスト (ACL)、およびストレージクラスが含まれます。詳細については、AppendObjectRequest をご覧ください。

レスポンスパラメーター

パラメーター

タイプ

説明

file

*AppendOnlyFile

追加可能なオブジェクト。このパラメーターは、err の値が nil の場合に有効です。詳細については、ReadOnlyFile をご覧ください。

err

error

ReadOnlyFile のステータス。エラーが発生した場合、err の値は nil にはなりません。

次の表に、AppendOnlyFile 操作について説明します。

操作

説明

Close() error

リソースを解放するためにファイルハンドルを閉じます。

Write(b []byte) (int, error)

b 内のデータをデータストリームに書き込み、書き込まれたバイト数と発生したエラーを返します。

WriteFrom(r io.Reader) (int64, error)

r 内のデータをデータストリームに書き込み、書き込まれたバイト数と発生したエラーを返します。

Stat() (os.FileInfo, error)

オブジェクトサイズ、最終更新時刻、メタデータなどのオブジェクト情報を照会します。

追加アップロードの基本操作:AppendObject

func (c *Client) AppendObject(ctx context.Context, request *AppendObjectRequest, optFns ...func(*Options)) (*AppendObjectResult, error)

リクエストパラメーター

パラメーター

タイプ

説明

ctx

context.Context

リクエストのコンテキスト。リクエストの合計継続時間を指定するために使用できます。

request

*AppendObjectRequest

特定の API 操作のパラメーター。詳細については、AppendObjectRequest をご覧ください。

optFns

...func(*Options)

オプション。操作レベルのパラメーター。詳細については、Options をご覧ください。

レスポンスパラメーター

パラメーター

タイプ

説明

result

*AppendObjectResult

操作に対するレスポンス。このパラメーターは、err の値が nil の場合に有効です。詳細については、AppendObjectResult をご覧ください。

err

error

リクエストのステータス。リクエストが失敗した場合、err の値は nil にはなりません。

AppendFile を呼び出して追加アップロードを実行する

package main

// パッケージをインポートします。
import (
	"context"
	"flag"
	"log"
	"os"

	"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss"
	"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss/credentials"
)

// グローバル変数を指定します。
var (
	region     string // バケットが配置されているリージョン。
	bucketName string // バケットの名前。
	objectName string // オブジェクトの名前。
)

// コマンドラインパラメーターを初期化するために使用される init 関数を指定します。
func init() {
	flag.StringVar(&region, "region", "", "バケットが配置されているリージョン。")
	flag.StringVar(&bucketName, "bucket", "", "バケットの名前。")
	flag.StringVar(&objectName, "object", "", "オブジェクトの名前。")
}

func main() {
	// コマンドラインパラメーターを解析します。
	flag.Parse()

	// バケット名が空かどうかを確認します。
	if len(bucketName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("無効なパラメーター、バケット名が必要です")
	}

	// リージョンが空かどうかを確認します。
	if len(region) == 0 {
		flag.PrintDefaults()
		log.Fatalf("無効なパラメーター、リージョンが必要です")
	}

	// オブジェクト名が空かどうかを確認します。
	if len(objectName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("無効なパラメーター、オブジェクト名が必要です")
	}

	// OSSClient インスタンスを構成します。
	cfg := oss.LoadDefaultConfig().
		WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()).
		WithRegion(region)

	// OSSClient インスタンスを作成します。
	client := oss.NewClient(cfg)

	// 追加可能なオブジェクトを作成します。
	f, err := client.AppendFile(context.TODO(),
		bucketName,
		objectName,
		func(ao *oss.AppendOptions) {
			ao.CreateParameter = &oss.AppendObjectRequest{
				Acl: oss.ObjectACLPrivate, // オブジェクトの ACL を private に設定します。
				Metadata: map[string]string{
					"user": "jack", // オブジェクトのメタデータを指定します。
				},
				Tagging: oss.Ptr("key=value"), // オブジェクトのタグを指定します。
			}
		})

	if err != nil {
		log.Fatalf("ファイルの追加に失敗しました %v", err)
	}
	defer f.Close() // 関数が完了したらファイルストリームが閉じられるようにします。


	// example1.txt という名前のローカルファイルを開きます。
	lf, err := os.Open("/local/dir/example1.txt")
	if err != nil {
		log.Fatalf("ローカルファイルを開けませんでした %v", err)
	}

	// example1.txt ファイルの内容を追加可能なオブジェクトに追加します。
	_, err = f.WriteFrom(lf)
	if err != nil {
		log.Fatalf("ファイルの追加に失敗しました %v", err)
	}
	lf.Close() // example1.txt ファイルを閉じます。

	// example2.txt という名前のローカルファイルを開きます。
	lf, err = os.Open("/local/dir/example2.txt")
	if err != nil {
		log.Fatalf("ローカルファイルを開けませんでした %v", err)
	}

	// example2.txt ファイルの内容を追加可能なオブジェクトに追加します。
	_, err = f.WriteFrom(lf)
	if err != nil {
		log.Fatalf("ファイルの追加に失敗しました %v", err)
	}
	lf.Close() // example2.txt ファイルを閉じます。

	// example3.txt という名前のローカルファイルの内容を読み取ります。
	lb, err := os.ReadFile("/local/dir/example3.txt")
	if err != nil {
		log.Fatalf("ローカルファイルの読み取りに失敗しました %v", err)
	}

	// example3.txt ファイルの内容を追加可能なオブジェクトに追加します。
	_, err = f.Write(lb)
	if err != nil {
		log.Fatalf("ファイルの追加に失敗しました %v", err)
	}

	// 追加アップロード操作のログを表示します。
	log.Printf("ファイルの追加に成功しました")
}

AppendObject を呼び出して追加アップロードを実行する

package main

// パッケージをインポートします。
import (
	"context"
	"flag"
	"log"
	"strings"

	"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss"
	"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss/credentials"
)

// グローバル変数を指定します。
var (
	region     string
	bucketName string
	objectName string
)

// コマンドラインパラメーターを初期化するために使用される init 関数を指定します。
func init() {
	flag.StringVar(&region, "region", "", "バケットが配置されているリージョン。")
	flag.StringVar(&bucketName, "bucket", "", "バケットの名前。")
	flag.StringVar(&objectName, "object", "", "オブジェクトの名前。")
}

func main() {
	// コマンドラインパラメーターを解析します。
	flag.Parse()

	// 追加操作の開始位置を指定します。
	var (
		position = int64(0)
	)

	// バケット名が空かどうかを確認します。
	if len(bucketName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("無効なパラメーター、バケット名が必要です")
	}

	// リージョンが空かどうかを確認します。
	if len(region) == 0 {
		flag.PrintDefaults()
		log.Fatalf("無効なパラメーター、リージョンが必要です")
	}

	// オブジェクト名が空かどうかを確認します。
	if len(objectName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("無効なパラメーター、オブジェクト名が必要です")
	}

	// デフォルトの構成を読み込み、認証情報プロバイダーとリージョンを指定します。
	cfg := oss.LoadDefaultConfig().
		WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()).
		WithRegion(region)

	// OSSClient インスタンスを作成します。
	client := oss.NewClient(cfg)

	// 追加するコンテンツを指定します。
	content := "hi append object"

	// 最初の追加操作を実行するための AppendObject リクエストを作成します。
	request := &oss.AppendObjectRequest{
		Bucket:   oss.Ptr(bucketName),
		Key:      oss.Ptr(objectName),
		Position: oss.Ptr(position),
		Body:     strings.NewReader(content),
	}

	// AppendObject リクエストを実行し、結果を処理します。
	// オブジェクトが初めて追加される場合、追加操作は 0 から開始されます。次の追加操作の位置はレスポンスに含まれています。
	result, err := client.AppendObject(context.TODO(), request)
	if err != nil {
		log.Fatalf("オブジェクトの追加に失敗しました %v", err)
	}

	// 2 回目の追加操作を実行するための AppendObject リクエストを作成します。
	request = &oss.AppendObjectRequest{
		Bucket:   oss.Ptr(bucketName),
		Key:      oss.Ptr(objectName),
		Position: oss.Ptr(result.NextPosition), // 最初の AppendObject リクエストへのレスポンスから NextPosition パラメーターの値を取得します。
		Body:     strings.NewReader("hi append object"),
	}

	// AppendObject リクエストを実行し、結果を処理します。
	result, err = client.AppendObject(context.TODO(), request)
	if err != nil {
		log.Fatalf("オブジェクトの追加に失敗しました %v", err)
	}

	log.Printf("オブジェクトの追加結果:%#v\n", result)
}

一般的なシナリオ

追加アップロードとプログレスバーの表示

package main

// パッケージをインポートします。
import (
	"context"
	"flag"
	"fmt"
	"log"
	"strings"

	"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss"
	"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss/credentials"
)

// グローバル変数を指定します。
var (
	region     string
	bucketName string
	objectName string
)

// コマンドラインパラメーターを初期化するために使用される init 関数を指定します。
func init() {
	flag.StringVar(&region, "region", "", "バケットが配置されているリージョン。")
	flag.StringVar(&bucketName, "bucket", "", "バケットの名前。")
	flag.StringVar(&objectName, "object", "", "オブジェクトの名前。")
}

func main() {
	// コマンドラインパラメーターを解析します。
	flag.Parse()

	// 追加操作の開始位置を指定します。
	var (
		position = int64(0)
	)

	// バケット名が指定されているかどうかを確認します。
	if len(bucketName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("無効なパラメーター、バケット名が必要です")
	}

	// リージョンが空かどうかを確認します。
	if len(region) == 0 {
		flag.PrintDefaults()
		log.Fatalf("無効なパラメーター、リージョンが必要です")
	}

	// オブジェクト名が指定されているかどうかを確認します。
	if len(objectName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("無効なパラメーター、オブジェクト名が必要です")
	}

	// デフォルトの構成を読み込み、認証情報プロバイダーとリージョンを指定します。
	cfg := oss.LoadDefaultConfig().
		WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()).
		WithRegion(region)

	// OSS クライアントを作成します。
	client := oss.NewClient(cfg)

	// 追加するコンテンツを指定します。
	content := "hi append object"

	// 最初の追加操作を実行するための AppendObject リクエストを作成します。
	request := &oss.AppendObjectRequest{
		Bucket:   oss.Ptr(bucketName),
		Key:      oss.Ptr(objectName),
		Position: oss.Ptr(position),
		Body:     strings.NewReader(content),
		ProgressFn: func(increment, transferred, total int64) {
			fmt.Printf("increment:%v, transferred:%v, total:%v\n", increment, transferred, total)
		}, // アップロードの進捗状況を照会するために使用される進捗状況コールバック関数を指定します。
	}

	// 最初の AppendObject リクエストを実行し、結果を処理します。
	// オブジェクトが初めて追加される場合、追加操作は 0 から開始されます。次の追加操作の位置はレスポンスに含まれています。
	result, err := client.AppendObject(context.TODO(), request)
	if err != nil {
		log.Fatalf("オブジェクトの追加に失敗しました %v", err)
	}

	// 2 回目の追加操作を実行するための AppendObject リクエストを作成します。
	request = &oss.AppendObjectRequest{
		Bucket:   oss.Ptr(bucketName),
		Key:      oss.Ptr(objectName),
		Position: oss.Ptr(result.NextPosition), // 最初の AppendObject リクエストへのレスポンスから NextPosition パラメーターの値を取得します。
		Body:     strings.NewReader("hi append object"),
		ProgressFn: func(increment, transferred, total int64) {
			fmt.Printf("increment:%v, transferred:%v, total:%v\n", increment, transferred, total)
		}, // アップロードの進捗状況を照会するために使用される進捗状況コールバック関数を指定します。
	}

	// AppendObject リクエストを実行し、結果を処理します。
	result, err = client.AppendObject(context.TODO(), request)
	if err != nil {
		log.Fatalf("オブジェクトの追加に失敗しました %v", err)
	}

	// 追加されたオブジェクトのバージョン ID をログに記録します。
	log.Printf("オブジェクトの追加結果:%#v\n", *result.VersionId)
}

参考資料

  • 追加アップロードの完全なサンプルコードについては、GitHub開発者ガイド をご覧ください。

  • 追加アップロードを実行するために呼び出すことができる高度な API 操作の詳細については、「AppendFile」をご参照ください。

  • 追加アップロードを実行するために呼び出すことができる API 操作の詳細については、「AppendObject」をご参照ください。