This topic describes how to use multipart upload.

To perform multipart upload, follow these steps:

  1. Initiate a multipart upload task.

    Use the InitiateMultipartUpload method to obtain an upload ID that is globally unique in OSS.

  2. Start multipart upload.

    Use the UploadPart method to upload the parts.

    Note
    • For parts with a same uploadId, parts are sequenced by their part numbers. If you have uploaded a part and use the same part number to upload another part, the later part will replace the former part.
    • OSS places the MD5 value of part data in ETag and returns the MD5 value to the user.
    • SDK automatically configures Content-MD5. OSS calculates the MD5 value of uploaded data and compares it with the MD5 value calculated by SDK. If the two values vary, the error code of InvalidDigest is returned.
  3. Complete multipart upload.

    After all of the parts have been uploaded, use the CompleteMultipartUpload method to combine these parts into a complete object.

The following code provides an example on how to use multipart upload:

#include <alibabacloud/oss/OssClient.h>

int64_t getFileSize(const std::string& file)
{
    std::fstream f(file, std::ios::in | std::ios::binary);
    f.seekg(0, f.end);
    int64_t size = f.tellg();
    f.close();
    return size;
}

using namespace AlibabaCloud::OSS;

int main(void)
{
    /* Initialize the OSS account information. */
    std::string AccessKeyId = "yourAccessKeyId";
    std::string AccessKeySecret = "yourAccessKeySecret";
    std::string Endpoint = "yourEndpoint";
    std::string BucketName = "yourBucketName";
    std::string ObjectName = "yourObjectName";

    /* Initialize network resources. */
    InitializeSdk();

    ClientConfiguration conf;
    OssClient client(Endpoint, AccessKeyId, AccessKeySecret, conf);
    InitiateMultipartUploadRequest initUploadRequest(BucketName, ObjectName);
    /* Optional. Specify the storage class. */
    //initUploadRequest.MetaData().addHeader("x-oss-storage-class", "Standard");

    /* Initiate the multipart upload task. */
    auto uploadIdResult = client.InitiateMultipartUpload(initUploadRequest);
    auto uploadId = uploadIdResult.result().UploadId();
    std::string fileToUpload = "yourLocalFilename";
    int64_t partSize = 100 * 1024;
    PartList partETagList;
    auto fileSize = getFileSize(fileToUpload);
    int partCount = static_cast<int>(fileSize / partSize);
    /* Calculate the number of upload parts. */
    if (fileSize % partSize ! = 0) {
        partCount++;
    }

    /* Upload each part sequentially. */
    for (int i = 1; i <= partCount; i++) {
        auto skipBytes = partSize * (i - 1);
        auto size = (partSize < fileSize - skipBytes) ? partSize : (fileSize - skipBytes);
        std::shared_ptr<std::iostream> content = std::make_shared<std::fstream>(fileToUpload, std::ios::in|std::ios::binary);
        content->seekg(skipBytes, std::ios::beg);

        UploadPartRequest uploadPartRequest(BucketName, ObjectName, content);
        uploadPartRequest.setContentLength(size);
        uploadPartRequest.setUploadId(uploadId);
        uploadPartRequest.setPartNumber(i);
        auto uploadPartOutcome = client.UploadPart(uploadPartRequest);
        if (uploadPartOutcome.isSuccess()) {
            Part part(i, uploadPartOutcome.result().ETag());
            partETagList.push_back(part);
        }
        else {
            std::cout << "uploadPart fail" <<
            ",code:" << uploadPartOutcome.error().Code() <<
            ",message:" << uploadPartOutcome.error().Message() <<
            ",requestId:" << uploadPartOutcome.error().RequestId() << std::endl;
        }

    }

    /* Complete multipart upload. */
    CompleteMultipartUploadRequest request(BucketName, ObjectName);
    request.setUploadId(uploadId);
    request.setPartList(partETagList);
    /* Optional. Set the ACL. */
    //request.setAcl(CannedAccessControlList::Private);

    auto outcome = client.CompleteMultipartUpload(request);

    if (! outcome.isSuccess()) {
        /* Handle exceptions. */
        std::cout << "CompleteMultipartUpload fail" <<
        ",code:" << outcome.error().Code() <<
        ",message:" << outcome.error().Message() <<
        ",requestId:" << outcome.error().RequestId() << std::endl;
        ShutdownSdk();
        return -1;
    }

    /* Release network resources. */
    ShutdownSdk();
    return 0;
}
Note Obtain the uploaded parts. You must provide the ETag value of each part to call CompleteMultipartUpload.

You can use either of the following methods to obtain the ETag value:

  • Method 1: When a part is uploaded, save and use the ETag value of the part that is included in the response.
  • Method 2: Call the ListParts operation to obtain the ETag values of the uploaded parts. In this example, the first method is used.

List uploaded parts

You can use the ListParts method to list all parts that are uploaded with the specified upload ID.
  • List all uploaded parts
    Note By default, the ListParts method can list up to 1,000 parts at a time. To list more than 1,000 parts, the results must be listed by page.
    The following code provides an example on how to list all uploaded parts:
    #include <alibabacloud/oss/OssClient.h>
    using namespace AlibabaCloud::OSS;
    
    int main(void)
    {
        /* Initialize the OSS account information. */
        std::string AccessKeyId = "yourAccessKeyId";
        std::string AccessKeySecret = "yourAccessKeySecret";
        std::string Endpoint = "yourEndpoint";
        std::string BucketName = "yourBucketName";
        std::string ObjectName = "yourObjectName";
    
        /* Initialize network resources. */
        InitializeSdk();
    
        ClientConfiguration conf;
        OssClient client(Endpoint, AccessKeyId, AccessKeySecret, conf);
    
        /* List the uploaded parts. The default number of parts returned is 1,000. */
        ListPartsRequest listuploadrequest(BucketName, ObjectName);
        listuploadrequest.setUploadId(uploadId);
        do {
            auto listuploadresult = client.ListParts(listuploadrequest);
            if (! listUploadResult.isSuccess()) {
                /* Handle exceptions. */
                std::cout << "ListParts fail" <<
                ",code:" << listuploadresult.error().Code() <<
                ",message:" << listuploadresult.error().Message() <<
                ",requestId:" << listuploadresult.error().RequestId() << std::endl;
                break;
            }
            else {
                for (const auto& part : listuploadresult.result().PartList()) {
                    std::cout << "part"<<
                    ",name:" << part.PartNumber() <<
                    ",size:" << part.Size() <<
                    ",etag:" << part.ETag() <<
                    ",lastmodify time:" << part.LastModified() << std::endl;
                }
            }
            listuploadrequest.setPartNumberMarker(listuploadresult.result().NextPartNumberMarker());
        } while (listuploadresult.result().IsTruncated());
    
        /* Release network resources. */
        ShutdownSdk();
        return 0;
    }
  • List all uploaded parts by page
    The following code provides an example on how to specify the maximum number of parts to list on each page and list all parts by page:
    #include <alibabacloud/oss/OssClient.h>
    using namespace AlibabaCloud::OSS;
    
    int main(void)
    {
        /* Initialize the OSS account information. */
        std::string AccessKeyId = "yourAccessKeyId";
        std::string AccessKeySecret = "yourAccessKeySecret";
        std::string Endpoint = "yourEndpoint";
        std::string BucketName = "yourBucketName";
        std::string ObjectName = "yourObjectName";
    
        /* Initialize network resources. */
        InitializeSdk();
    
        ClientConfiguration conf;
        OssClient client(Endpoint, AccessKeyId, AccessKeySecret, conf);
    
        /* List all uploaded parts by page. */
        /* Set the maximum number of parts to list on each page. */
        ListPartsRequest listuploadrequest(BucketName, ObjectName);
        listuploadrequest.setMaxParts(50);
        listuploadrequest.setUploadId(uploadId);
        do {
            listuploadresult = client.ListParts(listuploadrequest);
            if (! listUploadResult.isSuccess()) {
                /* Handle exceptions. */
                std::cout << "ListParts fail" <<
                ",code:" << outcome.error().Code() <<
                ",message:" << listuploadresult.error().Message() <<
                ",requestId:" << listuploadresult.error().RequestId() << std::endl;
                break;
            }
            else {
                for (const auto& part : listuploadresult.result().PartList()) {
                    std::cout << "part"<<
                    ",name:" << part.PartNumber() <<
                    ",size:" << part.Size() <<
                    ",etag:" << part.ETag() <<
                    ",lastmodify time:" << part.LastModified() << std::endl;
                }
            }  
            listuploadrequest.setPartNumberMarker(listuploadresult.result().NextPartNumberMarker());     
        } while (listuploadresult.result().IsTruncated());
    
        /* Release network resources. */
        ShutdownSdk();
        return 0;
    }

List multipart upload tasks

You can use the ListMultipartUploads method to list all ongoing multipart upload tasks (tasks that have been initiated but not completed or tasks that have been canceled).

  • List all multipart upload tasks
    Note By default, the ListMultipartUploads method can list up to 1,000 multipart upload tasks at a time. To list more than 1,000 multipart upload tasks, the results must be listed by page.

    The following code provides an example on how to list all multipart upload tasks:

    #include <alibabacloud/oss/OssClient.h>
    using namespace AlibabaCloud::OSS;
    
    int main(void)
    {
        /* Initialize the OSS account information. */
        std::string AccessKeyId = "yourAccessKeyId";
        std::string AccessKeySecret = "yourAccessKeySecret";
        std::string Endpoint = "yourEndpoint";
        std::string BucketName = "yourBucketName";
    
        /* Initialize network resources. */
        InitializeSdk();
    
        ClientConfiguration conf;
        OssClient client(Endpoint, AccessKeyId, AccessKeySecret, conf);
    
        /* List the multipart upload tasks. The default number of parts returned is 1,000. */
        ListMultipartUploadsRequest listmultiuploadrequest(BucketName);
        do {
            auto listresult = client.ListMultipartUploads(listmultiuploadrequest);
            if (! listresult.isSuccess()) {
                /* Handle exceptions. */
                std::cout << "ListMultipartUploads fail" <<
                ",code:" << listresult.error().Code() <<
                ",message:" << listresult.error().Message() <<
                ",requestId:" << listresult.error().RequestId() << std::endl;
                break;
            }
            else {
                for (const auto& part : listresult.result().MultipartUploadList()) {
                    std::cout << "part"<<
                    ",name:" << part.Key <<
                    ",uploadid:" << part.UploadId <<
                    ",initiated time:" << part.Initiated << std::endl;
                }
            }
            listmultiuploadrequest.setKeyMarker(listresult.result().NextKeyMarker()); 
            listmultiuploadrequest.setUploadIdMarker(listresult.result().NextUploadIdMarker()); 
        } while (listresult.result().IsTruncated());
    
        /* Release network resources. */
        ShutdownSdk();
        return 0;
    }
  • List all multipart upload tasks by page
    The following code provides an example on how to list all multipart upload tasks by page:
    #include <alibabacloud/oss/OssClient.h>
    using namespace AlibabaCloud::OSS;
    
    int main(void)
    {
        /* Initialize the OSS account information. */
        std::string AccessKeyId = "yourAccessKeyId";
        std::string AccessKeySecret = "yourAccessKeySecret";
        std::string Endpoint = "yourEndpoint";
        std::string BucketName = "yourBucketName";
    
        /* Initialize network resources. */
        InitializeSdk();
    
        ClientConfiguration conf;
        OssClient client(Endpoint, AccessKeyId, AccessKeySecret, conf);
    
        /* List all multipart upload tasks by page. */
        /* Set the maximum number of multipart upload tasks to list on each page. */
        ListMultipartUploadsRequest  listmultiuploadrequest(BucketName);
        listmultiuploadrequest.setMaxUploads(50);
        do {
            listresult = client.ListMultipartUploads(listmultiuploadrequest);
            if (! listresult.isSuccess()) {
                /* Handle exceptions. */
                std::cout << "ListMultipartUploads fail" <<
                ",code:" << listresult.error().Code() <<
                ",message:" << listresult.error().Message() <<
                ",requestId:" << listresult.error().RequestId() << std::endl;
                break;
            }
            else {
                for (const auto& part : listresult.result().MultipartUploadList()) {
                    std::cout << "part"<<
                    ",name:" << part.Key <<
                    ",uploadid:" << part.UploadId <<
                    ",initiated time:" << part.Initiated << std::endl;
                }
            }  
            listmultiuploadrequest.setKeyMarker(listresult.result().NextKeyMarker()); 
            listmultiuploadrequest.setUploadIdMarker(listresult.result().NextUploadIdMarker()); 
        } while (listresult.result().IsTruncated());
    
        /* Release network resources. */
        ShutdownSdk();
        return 0;
    }

Cancel a multipart upload task

The following code provides an example on how to cancel a multipart upload task:
#include <alibabacloud/oss/OssClient.h>
using namespace AlibabaCloud::OSS;

int main(void)
{
    /* Initialize the OSS account information. */
    std::string AccessKeyId = "yourAccessKeyId";
    std::string AccessKeySecret = "yourAccessKeySecret";
    std::string Endpoint = "yourEndpoint";
    std::string BucketName = "yourBucketName";
    std::string ObjectName = "yourObjectName";

    /* Initialize network resources. */
    InitializeSdk();

    ClientConfiguration conf;
    OssClient client(Endpoint, AccessKeyId, AccessKeySecret, conf);
    InitiateMultipartUploadRequest initUploadRequest(BucketName, ObjectName);

    /* Initiate the multipart upload task. */
    auto uploadIdResult = client.InitiateMultipartUpload(initUploadRequest);
    auto uploadId = uploadIdResult.result().UploadId();

    /* Cancel the multipart upload task. */
    AbortMultipartUploadRequest  abortUploadRequest(BucketName, ObjectName, uploadId);
    auto abortUploadIdResult = client.AbortMultipartUpload(abortUploadRequest);

    if (! abortUploadIdResult.isSuccess()) {
        /* Handle exceptions. */
        std::cout << "AbortMultipartUpload fail" <<
        ",code:" << outcome.error().Code() <<
        ",message:" << outcome.error().Message() <<
        ",requestId:" << outcome.error().RequestId() << std::endl;
        ShutdownSdk();
        return -1;
    }

    /* Release network resources. */
    ShutdownSdk();
    return 0;
}
Note If a multipart upload task is canceled, the upload ID can no longer be used to perform further operation. The parts uploaded with that upload ID are also deleted.