マルチパートアップロードは、大きなオブジェクトを複数のパートに分割し、それぞれを独立してアップロードします。すべてのパートがアップロードされた後、CompleteMultipartUpload を呼び出して、それらを完全なオブジェクトにアセンブルします。
前提条件
開始する前に、以下が準備できていることを確認してください。
Object Storage Service (OSS) バケット
oss:PutObject権限。詳細については、「RAM ユーザーへのカスタムポリシーのアタッチ」をご参照ください。環境変数として設定されたアクセス認証情報。詳細については、「アクセス認証情報の設定」をご参照ください。
仕組み
マルチパートアップロードは、3 つのステップで構成されます。
開始 —
Client.InitiateMultipartUploadを呼び出して、OSS から一意のアップロード ID を取得します。パートのアップロード —
Client.UploadPartを呼び出して、そのアップロード ID を使用して各パートをアップロードします。完了 —
Client.CompleteMultipartUploadを呼び出して、アップロードされたすべてのパートを最終的なオブジェクトにアセンブルします。
パート番号の動作:
パート番号は、最終的なオブジェクトにおけるパートの順序を定義します。既存のパート番号で新しいパートをアップロードすると、元のパートが上書きされます。
OSS は、アップロードされた各パートの MD5 ハッシュを
ETagレスポンスヘッダーで返します。その後、OSS SDK for Go によって計算されたハッシュと検証します。これらが異なる場合、OSS はInvalidDigestを返します。詳細については、「ETag 値を OSS MD5 ハッシュとして使用してデータ整合性を確認できますか」をご参照ください。
サンプルコードでは、リージョン cn-hangzhou とパブリックエンドポイントを使用しています。同じリージョン内の別の Alibaba Cloud サービスから OSS にアクセスするには、内部エンドポイントに切り替えてください。利用可能なリージョンとエンドポイントについては、「リージョンとエンドポイント」をご参照ください。ローカルファイルのアップロード
次の例では、ローカルファイルをメモリに読み込み、3 つのパートに分割し、goroutine を使用してパートを同時にアップロードしてから、アセンブルします。
package main
import (
"bufio"
"bytes"
"context"
"flag"
"io"
"log"
"os"
"sync"
"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
)
func init() {
flag.StringVar(®ion, "region", "", "The region in which the bucket is located.")
flag.StringVar(&bucketName, "bucket", "", "The name of the bucket.")
flag.StringVar(&objectName, "object", "", "The name of the object.")
}
func main() {
flag.Parse()
var uploadId string
if len(bucketName) == 0 {
flag.PrintDefaults()
log.Fatalf("invalid parameters, bucket name required")
}
if len(region) == 0 {
flag.PrintDefaults()
log.Fatalf("invalid parameters, region required")
}
if len(objectName) == 0 {
flag.PrintDefaults()
log.Fatalf("invalid parameters, object name required")
}
cfg := oss.LoadDefaultConfig().
WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()).
WithRegion(region)
client := oss.NewClient(cfg)
// マルチパートアップロードを開始し、アップロード ID を取得します。
initRequest := &oss.InitiateMultipartUploadRequest{
Bucket: oss.Ptr(bucketName),
Key: oss.Ptr(objectName),
}
initResult, err := client.InitiateMultipartUpload(context.TODO(), initRequest)
if err != nil {
log.Fatalf("failed to initiate multipart upload: %v", err)
}
log.Printf("upload ID: %s\n", *initResult.UploadId)
uploadId = *initResult.UploadId
var wg sync.WaitGroup
var parts []oss.UploadPart
var mu sync.Mutex
count := 3
// ローカルファイルをメモリに読み込みます。「yourLocalFile」を実際のファイルパスに置き換えてください。
file, err := os.Open("yourLocalFile")
if err != nil {
log.Fatalf("failed to open file: %v", err)
}
defer file.Close()
bufReader := bufio.NewReader(file)
content, err := io.ReadAll(bufReader)
if err != nil {
log.Fatalf("failed to read file: %v", err)
}
log.Printf("file size: %d bytes\n", len(content))
// ファイルをパートに分割し、同時にアップロードします。
chunkSize := len(content) / count
if chunkSize == 0 {
chunkSize = 1
}
for i := 0; i < count; i++ {
start := i * chunkSize
end := start + chunkSize
if i == count-1 {
end = len(content)
}
wg.Add(1)
go func(partNumber int, start, end int) {
defer wg.Done()
partRequest := &oss.UploadPartRequest{
Bucket: oss.Ptr(bucketName),
Key: oss.Ptr(objectName),
PartNumber: int32(partNumber),
UploadId: oss.Ptr(uploadId),
Body: bytes.NewReader(content[start:end]),
}
partResult, err := client.UploadPart(context.TODO(), partRequest)
if err != nil {
log.Fatalf("failed to upload part %d: %v", partNumber, err)
}
mu.Lock()
parts = append(parts, oss.UploadPart{
PartNumber: partRequest.PartNumber,
ETag: partResult.ETag,
})
mu.Unlock()
}(i+1, start, end)
}
wg.Wait()
// アップロードされたすべてのパートを最終的なオブジェクトにアセンブルします。
request := &oss.CompleteMultipartUploadRequest{
Bucket: oss.Ptr(bucketName),
Key: oss.Ptr(objectName),
UploadId: oss.Ptr(uploadId),
CompleteMultipartUpload: &oss.CompleteMultipartUpload{
Parts: parts,
},
}
result, err := client.CompleteMultipartUpload(context.TODO(), request)
if err != nil {
log.Fatalf("failed to complete multipart upload: %v", err)
}
log.Printf("multipart upload complete: %#v\n", result)
}その他の例
API リファレンス
操作 | 説明 |
マルチパートアップロードタスクを開始し、アップロード ID を返します | |
単一のパートをアップロードします | |
アップロードされたパートを完全なオブジェクトにアセンブルします | |
マルチパートアップロードタスクをキャンセルします | |
特定のタスクでアップロードされたパートをリスト表示します | |
バケット内の進行中のすべてのマルチパートアップロードタスクをリスト表示します。進行中のタスクとは、開始されたがまだ完了または中止されていないタスクのことです。 |
完全なサンプルコードについては、「GitHub」をご参照ください。