このトピックでは、オブジェクトを複数のパーツに分けてアップロードする方法について説明します。

マルチパートアップロードを有効にするには、次の手順を実行します。

  1. マルチパートアップロードイベントを開始します。

    Bucket.InitiateMultipartUpload を呼び出して、OSS で作成されたグローバルに一意な uploadId を返します。

  2. マルチパートアップロードタスクを開始します。

    Bucket.UploadPart を呼び出して、データを複数のパーツに分けてアップロードします。

    重要
    • 同じ uploadId を持つパーツは、それらのパーツ番号によって順序付けされます。 パーツをアップロードし、同じパーツ番号を使用して別のパーツをアップロードすると、後のパーツが前のパーツに置き換わります。
    • データパーツのMD5 値は ETag ヘッダーに含まれており、ユーザーに返されます。
    • OSS SDK は自動的に Content-MD5 を設定します。 OSS はアップロードされたデータの MD 5 値を計算し、それを SDK によって計算されたMD 5 値と比較します。 2 つの値が異なると、InvalidDigest エラーコードが返されます。
  3. マルチパートアップロードタスクを完了します。

    すべてのパーツをアップロードしたら、Bucket.CompleteMultipartUpload を呼び出してこれらのパーツを組み合わせて完全なオブジェクトにします。

次のコードは、マルチパートアップロードのプロセスを説明する完全な例として使用されています。

package main
import (
    "fmt"
    "os"
    "github.com/aliyun/aliyun-oss-go-sdk/oss"
)
func main() {
    // Creates an OSSClient instance.
    client, err := oss.New("<yourEndpoint>", "<yourAccessKeyId>", "<yourAccessKeySecret>")
    if err ! = nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }
    bucketName := "<yourBucketName>"
    objectName := "<yourObjectName>"
    locaFilename := "<yourLocalFilename>"
    // Obtains a bucket.
    bucket, err := client.Bucket(bucketName)
    if err ! = nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }
    chunks, err := oss.SplitFileByPartNum(locaFilename, 3)
    fd, err := os.Open(locaFilename)
    defer fd.Close()
    // Step 1: Initiates a multipart upload event.
    imur, err := bucket.InitiateMultipartUpload(objectName)
    // Step 2: Uploads parts.
    var parts []oss.UploadPart
    for _, chunk := range chunks {
        fd.Seek(chunk.Offset, os.SEEK_SET)
        // Calls UploadPart to upload each part.
        part, err := bucket.UploadPart(imur, fd, chunk.Size, chunk.Number)
        if err ! = nil {
            fmt.Println("Error:", err)
            os.Exit(-1)
        }
        parts = append(parts, part)
    }
    // Step 3: Completes the multipart upload task.
    cmur, err := bucket.CompleteMultipartUpload(imur, parts)
    if err ! = nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }
    fmt.Println("cmur:", cmur)
}

マルチパートアップロードイベントのキャンセル

次のコードを実行してマルチパートアップロードイベントをキャンセルします。

package main
import (
    "fmt"
    "os"
    "github.com/aliyun/aliyun-oss-go-sdk/oss"
)
func main() {
    // Creates an OSSClient instance.
    client, err := oss.New("<yourEndpoint>", "<yourAccessKeyId>", "<yourAccessKeySecret>")
    if err ! = nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }
    // Obtains a bucket.
    bucket, err := client.Bucket("<yourBucketName>")
    if err ! = nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }
    // Initiates a multipart upload event.
    imur, err := bucket.InitiateMultipartUpload("<yourObjectName>")
    if err ! = nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }
    // Cancels the multipart upload event.
    err = bucket.AbortMultipartUpload(imur)
    if err ! = nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }
}

アップロードしたパーツの列挙

次のコードを実行して、マルチパートアップロードイベントでアップロードされたパーツを列挙します。

package main
import (
    "fmt"
    "os"
    "github.com/aliyun/aliyun-oss-go-sdk/oss"
)
func main() {
    // Creates an OSSClient instance.
    client, err := oss.New("<yourEndpoint>", "<yourAccessKeyId>", "<yourAccessKeySecret>")
    if err ! = nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }
    bucketName := "<yourBucketName>"
    objectName := "<yourObjectName>"
    locaFilename := "<yourLocalFilename>"
    uploadID := "<yourUploadID>"
    // Obtains a bucket.
    bucket, err := client.Bucket(bucketName)
    if err ! = nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }
    // Splits the local file into multiple parts (3 parts in this example).
    chunks, err := oss.SplitFileByPartNum(locaFilename, 3)
    fd, err := os.Open(locaFilename)
    defer fd.Close()
    // Initiates a multipart upload event.
    imur, err := bucket.InitiateMultipartUpload(objectName)
    uploadID = imur.UploadID
    fmt.Println("InitiateMultipartUpload UploadID: ", uploadID)
    if err ! = nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }
    // Uploads parts.
    var parts []oss.UploadPart
    for _, chunk := range chunks {
        fd.Seek(chunk.Offset, os.SEEK_SET)
        // Calls UploadPart to upload each part.
        part, err := bucket.UploadPart(imur, fd, chunk.Size, chunk.Number)
        if err ! = nil {
            fmt.Println("Error:", err)
            os.Exit(-1)
        }
        fmt.Println("UploadPartNumber: ", part.PartNumber, ", ETag: ", part.ETag)
        parts = append(parts, part)
    }
    // Lists uploaded parts based on InitiateMultipartUploadResult
    lsRes, err := bucket.ListUploadedParts(imur)
    if err ! = nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }
    // Prints the uploaded parts. 
    fmt.Println("\nParts:", lsRes.UploadedParts)
    for _, upload := range lsRes.UploadedParts {
        fmt.Println("List PartNumber:  ", upload.PartNumber, ", ETag: " ,upload.ETag, ", LastModified: ", upload.LastModified)
    }
    // Generates InitiateMultipartUploadResult based on objectName and UploadID, and then list all uploaded parts, which applies to scenarios where you know the objectName and UploadID.
    var imur_with_uploadid oss.InitiateMultipartUploadResult
    imur_with_uploadid.Key = objectName
    imur_with_uploadid.UploadID = uploadID
    // Lists uploaded parts.
    lsRes, err = bucket.ListUploadedParts(imur_with_uploadid)
    if err ! = nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }
    // Prints the uploaded parts.
    fmt.Println("\nListUploadedParts by UploadID: ", uploadID)
    for _, upload := range lsRes.UploadedParts {
        fmt.Println("List PartNumber:  ", upload.PartNumber, ", ETag: " ,upload.ETag, ", LastModified: ", upload.LastModified)
    }
    // Completes the multipart upload task.
    cmur, err := bucket.CompleteMultipartUpload(imur, parts)
    if err ! = nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }
    fmt.Println("cmur:", cmur)
}

バケットのすべてのパートアップロードイベントの列挙

Bucket.ListMultipartUploads を呼び出して、進行中のすべてのマルチパートアップロードイベント (開始されたが完了していないイベント、またはキャンセルされたイベント) を列挙します。 以下のパラメータを設定できます。

パラメーター 説明
Delimiter オブジェクト名をグループ化するために使用されるスラッシュ (/) の区切り記号を指定します。 名前に指定されたプレフィックスが含まれ、その間に区切り記号が最初に現れるオブジェクトはすべて、エレメントグループを形成します。
MaxUploads パートアップロードイベントの最大数を指定します。 設定できる最大値 (これも既定値) は 1,000 です。
KeyMarker オブジェクト名が "KeyMarker" 値の後に続く文字でアルファベット順に始まるすべてのマルチパートアップロードイベントを列挙します。 このパラメーターを "UploadIDMarke"r と一緒に使用して、返される結果の始点を指定できます。
Prefix 返されるオブジェクト名に含める必要があるプレフィックスを指定します。 クエリにプレフィックスを使用すると、返されるオブジェクト名にはそのプレフィックスが含まれます。
UploadIDMarker "UploadIDMarker "は、返された結果の始点を指定するため、 "KeyMarker" パラメーターと一緒に使用されます。
  • "KeyMarker" が設定されていない場合、このパラメーターは無視されます。
  • "KeyMarker" が設定されている場合、クエリの結果には以下が含まれます。
    • すべてのオブジェクト名がアルファベット順で "KeyMarker" 値の後に続く文字で始まるマルチパートアップロードイベント。
    • オブジェクト名は "KeyMarker" の値に等しいが、オブジェクトのアップロード ID は "UploadIDMarker" の値よりも大きいマルチパートアップロードイベント。
  • 既定値のパラメーターを使用します。
    package main
    import (
        "fmt"
        "os"
        "github.com/aliyun/aliyun-oss-go-sdk/oss"
    )
    func main() {
        // Creates an OSSClient instance.
        client, err := oss.New("<yourEndpoint>", "<yourAccessKeyId>", "<yourAccessKeySecret>")
        if err ! = nil {
            fmt.Println("Error:", err)
            os.Exit(-1)
        }
        // Obtains a bucket.
        bucketName := "<yourBucketName>"
        bucket, err := client.Bucket(bucketName)
        if err ! = nil {
            fmt.Println("Error:", err)
            os.Exit(-1)
        }
        // Lists all multipart upload events.
        keyMarker := ""
        uploadIdMarker := ""
        for {
            // 1000 records are listed at a time by default. 
            lsRes, err := bucket.ListMultipartUploads(oss.KeyMarker(keyMarker), oss.UploadIDMarker(uploadIdMarker))
            if err ! = nil {
                fmt.Println("Error:", err)
                os.Exit(-1)
            }
            // Prints multipart upload events. 
            for _, upload := range lsRes.Uploads {
                fmt.Println("Upload: ", upload.Key, ", UploadID: ",upload.UploadID)
            }
            if lsRes.IsTruncated {
                keyMarker = lsRes.NextKeyMarker
                uploadIdMarker = lsRes.NextUploadIDMarker
            } else {
                break
            }
        }
    }
  • 次のコードを実行して、指定されたプレフィックスを持つマルチパートアップロードイベントを列挙します。
        lsRes, err := bucket.ListMultipartUploads(oss.Prefix("<yourObjectNamePrefix>"))
        if err ! = nil {
            fmt.Println("Error:", err)
            os.Exit(-1)
        }
        fmt.Println("Uploads:", lsRes.Uploads)
  • 以下のコードを実行して、一度に最大 100 個のマルチパートアップロードイベントを列挙します。
        lsRes, err := bucket.ListMultipartUploads(oss.MaxUploads(100))
        if err ! = nil {
            fmt.Println("Error:", err)
            os.Exit(-1)
        }
        fmt.Println("Uploads:", lsRes.Uploads)
  • 次のコードを実行して、指定されたプレフィックスと最大数を持つマルチパートアップロードイベントを列挙します。
        lsRes, err := bucket.ListMultipartUploads(oss.Prefix("<yourObjectNamePrefix>"), oss.MaxUploads(100))
        if err ! = nil {
            fmt.Println("Error:", err)
            os.Exit(-1)
        }
        fmt.Println("Uploads:", lsRes.Uploads)