By using the multipart upload feature provided by OSS, you can split a large object into multiple parts and upload them separately. After all parts are uploaded, call the CompleteMultipartUpload operation to combine these parts into a single object to implement resumable upload.

Process

To upload an object by using multipart upload, perform the following steps:

  1. Initialize a multipart upload task.

    Call the InitiateMultipartUploadRequest method to obtain a unique upload ID.

  2. Upload parts.

    Call the UploadPartRequest method to upload parts.

    Note
    • For parts that are uploaded by a multipart upload task with a specific upload ID, part numbers identify their relative positions in an object. If you upload a part with the same part number as an existing part, the existing part is overwritten by the uploaded part.
    • OSS includes the MD5 hash of part data in the ETag header and returns the MD5 hash to the user.
    • OSS calculates the MD5 hash of uploaded data and compares the MD5 hash with the MD5 hash calculated by the SDK. If the two hashes are different, the InvalidDigest error code is returned.
  3. Complete the multipart upload task.

    After all parts are uploaded, call the CompleteMultipartUploadRequest method to combine the parts into a complete object.

Complete sample code

The following code provides a complete example that describes the process of multipart upload:

using Aliyun.OSS;

// Set yourEndpoint to the endpoint of the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set yourEndpoint to https://oss-cn-hangzhou.aliyuncs.com. 
var endpoint = "yourEndpoint";
// Security risks may arise if you use the AccessKey pair of an Alibaba Cloud account to access Object Storage Service (OSS) because the account has permissions on all API operations. We recommend that you use a RAM user to call API operations or perform routine O&M. To create a RAM user, log on to the RAM console. 
var accessKeyId = "yourAccessKeyId";
var accessKeySecret = "yourAccessKeySecret";
// Specify the name of the bucket. 
var bucketName = "examplebucket";
// Specify the full path of the object. The full path cannot contain the name of the bucket. 
var objectName = "exampleobject.txt";
// Specify the full path of the local file that you want to upload. By default, if you do not specify the full path of the local file, the local file is uploaded from the path of the project to which the sample program belongs. 
var localFilename = "D:\\localpath\\examplefile.txt";
// Create an OSSClient instance. 
var client = new OssClient(endpoint, accessKeyId, accessKeySecret);

// Initiate the multipart upload task and obtain the upload ID in the response. 
var uploadId = "";
try
{
    // Specify the name of the uploaded object and the bucket for the object. You can configure object metadata in InitiateMultipartUploadRequest. However, you do not need to specify ContentLength. 
    var request = new InitiateMultipartUploadRequest(bucketName, objectName);
    var result = client.InitiateMultipartUpload(request);
    uploadId = result.UploadId;
    // Display the upload ID. 
    Console.WriteLine("Init multi part upload succeeded");
    Console.WriteLine("Upload Id:{0}", result.UploadId);
}
catch (Exception ex)
{
    Console.WriteLine("Init multi part upload failed, {0}", ex.Message);
}
// Calculate the total number of parts. 
var partSize = 100 * 1024;
var fi = new FileInfo(localFilename);
var fileSize = fi.Length;
var partCount = fileSize / partSize;
if (fileSize % partSize != 0)
{
    partCount++;
}
// Start the multipart upload task. partETags is a list of PartETags. OSS verifies the validity of each part after it receives the list of parts. After all parts are verified, OSS combines these parts into a complete object. 
var partETags = new List<PartETag>();
try
{
    using (var fs = File.Open(localFilename, FileMode.Open))
    {
        for (var i = 0; i < partCount; i++)
        {
            var skipBytes = (long)partSize * i;
            // Find the start position of the current multipart upload task. 
            fs.Seek(skipBytes, 0);
            // Calculate the part size in this upload. The size of the last part is the size of the remainder after the object is split by the calculated part size. 
            var size = (partSize < fileSize - skipBytes) ? partSize : (fileSize - skipBytes);
            var request = new UploadPartRequest(bucketName, objectName, uploadId)
            {
                InputStream = fs,
                PartSize = size,
                PartNumber = i + 1
            };
            // Call UploadPart to upload parts. The returned results contain the ETag values of parts. 
            var result = client.UploadPart(request);
            partETags.Add(result.PartETag);
            Console.WriteLine("finish {0}/{1}", partETags.Count, partCount);
        }
        Console.WriteLine("Put multi part upload succeeded");
    }
}
catch (Exception ex)
{
    Console.WriteLine("Put multi part upload failed, {0}", ex.Message);
}
// Complete the multipart upload task. 
try
{
    var completeMultipartUploadRequest = new CompleteMultipartUploadRequest(bucketName, objectName, uploadId);
    foreach (var partETag in partETags)
    {
        completeMultipartUploadRequest.PartETags.Add(partETag);
    }
    var result = client.CompleteMultipartUpload(completeMultipartUploadRequest);
    Console.WriteLine("complete multi part succeeded");
}
catch (Exception ex)
{
    Console.WriteLine("complete multi part failed, {0}", ex.Message);
}

Cancel a multipart upload task

You can call the client.AbortMultipartUpload method to cancel a multipart upload task. If you cancel the multipart upload task, the upload ID cannot be used to upload any parts. The parts that are uploaded by using the multipart upload task are deleted.

The following code provides an example on how to cancel a multipart upload task:

using Aliyun.OSS;

// Set yourEndpoint to the endpoint of the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set yourEndpoint to https://oss-cn-hangzhou.aliyuncs.com. 
var endpoint = "yourEndpoint";
// Security risks may arise if you use the AccessKey pair of an Alibaba Cloud account to access OSS because the account has permissions on all API operations. We recommend that you use a RAM user to call API operations or perform routine O&M. To create a RAM user, log on to the RAM console. 
var accessKeyId = "yourAccessKeyId";
var accessKeySecret = "yourAccessKeySecret";
// Specify the name of the bucket. 
var bucketName = "examplebucket";
// Specify the full path of the object. The full path cannot contain the name of the bucket. 
var objectName = "exampleobject.txt";
// Specify the upload ID. 
var uploadId = "yourUploadId";

// Create an OSSClient instance. 
var client = new OssClient(endpoint, accessKeyId, accessKeySecret);
// Initiate a multipart upload task. 
try
{
    var request = new InitiateMultipartUploadRequest(bucketName, objectName);
    var result = client.InitiateMultipartUpload(request);
    uploadId = result.UploadId;
    // Display the upload ID. 
    Console.WriteLine("Init multi part upload succeeded");
    Console.WriteLine("Upload Id:{0}", result.UploadId);
}
catch (Exception ex)
{
    Console.WriteLine("Init multi part upload failed, {0}", ex.Message);
}
// Cancel the multipart upload task. 
try
{
    var request = new AbortMultipartUploadRequest(bucketName, objectName, uploadId);
    client.AbortMultipartUpload(request);
    Console.WriteLine("Abort multi part succeeded, {0}", uploadId);
}
catch (Exception ex)
{
    Console.WriteLine("Abort multi part failed, {0}", ex.Message);
}

List uploaded parts

The following code provides an example on how to list uploaded parts:

using Aliyun.OSS;
// Set yourEndpoint to the endpoint of the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set yourEndpoint to https://oss-cn-hangzhou.aliyuncs.com. 
var endpoint = "yourEndpoint";
// Security risks may arise if you use the AccessKey pair of an Alibaba Cloud account to access OSS because the account has permissions on all API operations. We recommend that you use a RAM user to call API operations or perform routine O&M. To create a RAM user, log on to the RAM console. 
var accessKeyId = "yourAccessKeyId";
var accessKeySecret = "yourAccessKeySecret";
// Specify the name of the bucket. 
var bucketName = "examplebucket";
// Specify the full path of the object. The full path cannot contain the name of the bucket. 
var objectName = "exampleobject.txt";
// Specify the upload ID. 
var uploadId = "yourUploadId";

// Create an OSSClient instance. 
var client = new OssClient(endpoint, accessKeyId, accessKeySecret);
try
{
    PartListing listPartsResult = null;
    var nextMarker = 0;
    do 
    {
        var listPartsRequest = new ListPartsRequest(bucketName, objectName, uploadId) 
        {
            PartNumberMarker = nextMarker,
        };
        // List uploaded parts. 
        listPartsResult = client.ListParts(listPartsRequest);
        Console.WriteLine("List parts succeeded");
        // Display the information about all uploaded parts. 
        var parts = listPartsResult.Parts;
        foreach (var part in parts)
        {
            Console.WriteLine("partNumber: {0}, ETag: {1}, Size: {2}", part.PartNumber, part.ETag, part.Size);
        }
        nextMarker = listPartsResult.NextPartNumberMarker;
    } while (listPartsResult.IsTruncated);
}
catch (Exception ex)
{
    Console.WriteLine("List parts failed, {0}", ex.Message);
}

List multipart upload tasks

You can call the ossClient.listMultipartUploads method to list all ongoing multipart upload tasks. Ongoing multipart upload tasks are tasks that have been initiated but are not completed and tasks that have been canceled. The following table describes the parameters that you can configure when you list all ongoing multipart upload tasks.

Parameter Description Method
prefix Specifies that the returned object name must contain a specified prefix. Note that if you use a prefix for a query, the returned object name contains the prefix. ListMultipartUploadsRequest.setPrefix(String prefix)
delimiter Groups objects by name. Specifies the character used to group multipart upload tasks by name. Multipart upload tasks whose names contain the same string that starts with the prefix and ends with the first occurrence of the specified delimiter are grouped as a single result element. ListMultipartUploadsRequest.setDelimiter(String delimiter)
maxUploads Specifies the maximum number of multipart upload tasks to return each time. Default value: 1000. Maximum value: 1000. ListMultipartUploadsRequest.setMaxUploads(Integer maxUploads)
keyMarker Specifies the position from which the list operation starts. All ongoing multipart upload tasks initiated for objects whose names are alphabetically after the keyMarker value are listed. You can use this parameter with the uploadIdMarker parameter to specify the start position from which to list the returned results. ListMultipartUploadsRequest.setKeyMarker(String keyMarker)
uploadIdMarker Specifies the start position from which to list returned results. This parameter is used together with the keyMarker parameter. If the keyMarker parameter is not configured, the uploadIdMarker parameter is invalid. If the keyMarker parameter is configured, the query results include the following items:
  • All objects whose names are alphabetically after the keyMarker value.
  • All multipart upload tasks with the same object name as the keyMarker value and an upload ID that is greater than the uploadIdMarker value.
ListMultipartUploadsRequest.setUploadIdMarker(String uploadIdMarker)

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

using Aliyun.OSS;
// Set yourEndpoint to the endpoint of the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set yourEndpoint to https://oss-cn-hangzhou.aliyuncs.com. 
var endpoint = "yourEndpoint";
// Security risks may arise if you use the AccessKey pair of an Alibaba Cloud account to access OSS because the account has permissions on all API operations. We recommend that you use a RAM user to call API operations or perform routine O&M. To create a RAM user, log on to the RAM console. 
var accessKeyId = "yourAccessKeyId";
var accessKeySecret = "yourAccessKeySecret";
// Specify the name of the bucket. 
var bucketName = "examplebucket";

// Create an OSSClient instance. 
var client = new OssClient(endpoint, accessKeyId, accessKeySecret);
try
{
    MultipartUploadListing multipartUploadListing = null;
    var nextMarker = string.Empty;
    do
    {
        // List multipart upload tasks. 
        var request = new ListMultipartUploadsRequest(bucketName)
        {
            KeyMarker = nextMarker,
        };
        multipartUploadListing = client.ListMultipartUploads(request);
        Console.WriteLine("List multi part succeeded");
        // List the information about each multipart upload task. 
        foreach (var mu in multipartUploadListing.MultipartUploads)
        {
            Console.WriteLine("Key: {0},  UploadId: {1}", mu.Key, mu.UploadId);
        }
        // If the value of the isTruncated field in the returned result is false, values of nextKeyMarker and nextUploadIdMarker are returned and used as the start point for the next read. 
        nextMarker = multipartUploadListing.NextKeyMarker;
    } while (multipartUploadListing.IsTruncated);
}
catch (Exception ex)
{
    Console.WriteLine("List multi part uploads failed, {0}", ex.Message);
}

List multipart upload tasks by specifying a prefix and the maximum number of records to return

The following code provides an example on how to list multipart upload tasks by specifying a prefix and the maximum number of records to return:

using Aliyun.OSS;
// Set yourEndpoint to the endpoint of the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set yourEndpoint to https://oss-cn-hangzhou.aliyuncs.com. 
var endpoint = "yourEndpoint";
// Security risks may arise if you use the AccessKey pair of an Alibaba Cloud account to access OSS because the account has permissions on all API operations. We recommend that you use a RAM user to call API operations or perform routine O&M. To create a RAM user, log on to the RAM console. 
var accessKeyId = "yourAccessKeyId";
var accessKeySecret = "yourAccessKeySecret";
// Specify the name of the bucket. 
var bucketName = "examplebucket";

// Specify the prefix. 
var prefix = "yourObjectPrefix";
// Specify the maximum number of records to return as 100. 
var maxUploads = 100;
// Create an OSSClient instance. 
var client = new OssClient(endpoint, accessKeyId, accessKeySecret);
try
{
    MultipartUploadListing multipartUploadListing = null;
    var nextMarker = string.Empty;
    do
    {
        // List multipart upload tasks. By default, 1,000 multipart upload tasks are listed. 
        var request = new ListMultipartUploadsRequest(bucketName)
        {
            KeyMarker = nextMarker,
            // Specify the prefix. 
            Prefix = prefix,
            // Specify the maximum number of records to return. 
            MaxUploads = maxUploads,
        };
        multipartUploadListing = client.ListMultipartUploads(request);
        Console.WriteLine("List multi part succeeded");
        // List the information about each multipart upload task. 
        foreach (var mu in multipartUploadListing.MultipartUploads)
        {
            Console.WriteLine("Key: {0},  UploadId: {1}", mu.Key, mu.UploadId);
        }
        nextMarker = multipartUploadListing.NextKeyMarker;
    } while (multipartUploadListing.IsTruncated);
}
catch (Exception ex)
{
    Console.WriteLine("List multi part uploads failed, {0}", ex.Message);
}

References

  • For more information about the complete sample code for multipart upload, visit GitHub.
  • The following API operations are required to perform multipart upload:
    • The API operation that you can call to initiate a multipart upload task. For more information, see InitiateMultipartUpload.
    • The API operation that you can call to upload data by part. For more information, see UploadPart.
    • The API operation that you can call to complete a multipart upload task. For more information, see CompleteMultipartUpload.
  • For more information about the API operation that you can call to cancel a multipart upload task, see AbortMultipartUpload.
  • For more information about the API operation that you can call to list the uploaded parts, see ListParts.
  • For more information about the API operation that you can call to list all ongoing multipart upload tasks, see ListMultipartUploads. Ongoing multipart upload tasks include tasks that have been initiated but are not completed and tasks that are canceled.