Help Center> Object Storage Service> iOS> Object Upload> Performing a Multipart Upload
Updated on 2024-05-08 GMT+08:00

Performing a Multipart Upload

Multipart upload is applicable to many scenarios, including:

  • Files to be uploaded are larger than 100 MB.
  • The network condition is poor. Connection to the OBS server is constantly down.
  • Sizes of files to be uploaded are uncertain.

Multipart upload consists of three phases:

  1. Initialize a multipart upload (initiateMultipartUpload).
  2. Upload parts one by one or concurrently (uploadPart).
  3. Combine parts (completeMultipartUpload) or abort the multipart upload (abortMultipartUpload).

Initiating a Multipart Upload

Before using a multipart upload, you need to first initiate it. This operation will return an upload ID (globally unique identifier) created by the OBS server to identify the multipart upload. You can use this upload ID to initiate related operations, such as aborting a multipart upload, listing multipart uploads, and listing uploaded parts.

You can call initiateMultipartUpload to initiate a multipart upload.

static OBSClient *client;
NSString *endPoint = @"your-endpoint";
// Hard-coded or plaintext AK/SK are risky. For security purposes, encrypt your AK/SK and store them in the configuration file or environment variables. In this example, the AK/SK are stored in environment variables for identity authentication. Before running this example, configure environment variables AccessKeyID and SecretAccessKey.
// Obtain an AK/SK pair on the management console. For details, see https://support.huaweicloud.com/intl/en-us/usermanual-ca/ca_01_0003.html.
char* ak_env = getenv("AccessKeyID");
char* sk_env = getenv("SecretAccessKey");
NSString *AK = [NSString stringWithUTF8String:ak_env];
NSString *SK = [NSString stringWithUTF8String:sk_env];

// Initialize identity authentication.
OBSStaticCredentialProvider *credentialProvider = [[OBSStaticCredentialProvider alloc] initWithAccessKey:AK secretKey:SK];
    
//Initialize service configuration.
OBSServiceConfiguration *conf = [[OBSServiceConfiguration alloc] initWithURLString:endPoint credentialProvider:credentialProvider];
    
// Initialize an instance of OBSClient.
client = [[OBSClient alloc] initWithConfiguration:conf];
    
// Initiate a multipart upload.
OBSInitiateMultipartUploadRequest *request = [[OBSInitiateMultipartUploadRequest alloc]initWithBucketName:@"bucketname" objectKey:@"objectname"];
    
[client initiateMultipartUpload:request completionHandler:^(OBSInitiateMultipartUploadResponse *response, NSError *error) {
    NSLog(@"%@",response);
}];
  • The upload ID of the multipart upload returned by response.uploadID will be used in follow-up operations.
  • In OBSInitiateMultipartUploadRequest, you can specify the MIME type, storage class, and customized metadata for the object. In addition, you can set the type of objects to be upload by setting customContentType.
  • When background is set to YES, background upload is enabled.

Uploading Parts

After initiating a multipart upload, you can specify the object name and upload ID to upload parts. Each part has a part number (ranging from 1 to 10000). For parts with the same upload ID, their part numbers are unique and identify their relative location in the object. If you use the same part number to upload two parts, the latter one uploaded will overwrite the former one. Except for the last uploaded part whose size ranges from 0 to 5 GB, sizes of the other parts range from 100 KB to 5 GB. Parts can be uploaded in random order, or even through different processes or machines. OBS will combine them into a final object based on their part numbers.

You can call uploadPart to upload parts.

static OBSClient *client;
NSString *endPoint = @"your-endpoint";

// Hard-coded or plaintext AK/SK are risky. For security purposes, encrypt your AK/SK and store them in the configuration file or environment variables. In this example, the AK/SK are stored in environment variables for identity authentication. Before running this example, configure environment variables AccessKeyID and SecretAccessKey.
// Obtain an AK/SK pair on the management console. For details, see https://support.huaweicloud.com/intl/en-us/usermanual-ca/ca_01_0003.html.
char* ak_env = getenv("AccessKeyID");
char* sk_env = getenv("SecretAccessKey");
NSString *AK = [NSString stringWithUTF8String:ak_env];
NSString *SK = [NSString stringWithUTF8String:sk_env];

// Initialize identity authentication.
OBSStaticCredentialProvider *credentialProvider = [[OBSStaticCredentialProvider alloc] initWithAccessKey:AK secretKey:SK];
    
//Initialize service configuration.
OBSServiceConfiguration *conf = [[OBSServiceConfiguration alloc] initWithURLString:endPoint credentialProvider:credentialProvider];
   
// Initialize an instance of OBSClient.
client = [[OBSClient alloc] initWithConfiguration:conf];
NSString *filePath = [[NSBundle mainBundle]pathForResource:@"fileName" ofType:@"Type"];
// First part
OBSUploadPartWithFileRequest* fileRequest_first =
[[OBSUploadPartWithFileRequest alloc]initWithBucketName:@"bucket-ios-test03"
                                                  objectkey:@"MultiPart"
                                                 partNumber:[NSNumber numberWithInt:1]
                                                   uploadID:@"uploadID"
                                             uploadFilePath:filePath];
// Enable background upload. When an application is switched to the background, the ongoing upload continues.
fileRequest_first.background = YES; 
    
[client uploadPart:fileRequest_first completionHandler:^(OBSUploadPartResponse *response, NSError *error) {
    NSLog(@"Part one");
}];
    
// Second part
OBSUploadPartWithFileRequest* fileRequest_sec =
[[OBSUploadPartWithFileRequest alloc]initWithBucketName:@"bucket-ios-test03"
                                                  objectkey:@"MultiPart"
                                                 partNumber:[NSNumber numberWithInt:2]
                                                   uploadID:@"uploadID"
                                             uploadFilePath:filePath];
    
[client uploadPart:fileRequest_sec completionHandler:^(OBSUploadPartResponse *response, NSError *error) {
    NSLog(@"Part two");
}];
  • Except the part last uploaded, other parts must be larger than 100 KB. Part sizes will not be verified during upload because which one is last uploaded is not identified until parts are combined.
  • OBS will return ETags (MD5 values) of the received parts to users.
  • Part numbers range from 1 to 10000. If a part number exceeds this range, OBS will return error 400 Bad Request.
  • The minimum part size supported by an OBS 3.0 bucket is 100 KB, and the minimum part size supported by an OBS 2.0 bucket is 5 MB. You are advised to perform multipart upload to OBS 3.0 buckets.

Combining Parts

After all parts are uploaded, call the API for combining parts to form the object. Before this operation, valid part numbers and ETags of all parts must be sent to OBS. After receiving this information, OBS verifies the validity of each part one by one. After all parts pass the verification, OBS combines these parts to form the final object.

You can call completeMultipartUpload to combine parts.

static OBSClient *client;
NSString *endPoint = @"your-endpoint";

// Hard-coded or plaintext AK/SK are risky. For security purposes, encrypt your AK/SK and store them in the configuration file or environment variables. In this example, the AK/SK are stored in environment variables for identity authentication. Before running this example, configure environment variables AccessKeyID and SecretAccessKey.
// Obtain an AK/SK pair on the management console. For details, see https://support.huaweicloud.com/intl/en-us/usermanual-ca/ca_01_0003.html.
char* ak_env = getenv("AccessKeyID");
char* sk_env = getenv("SecretAccessKey");
NSString *AK = [NSString stringWithUTF8String:ak_env];
NSString *SK = [NSString stringWithUTF8String:sk_env];

// Initialize identity authentication.
OBSStaticCredentialProvider *credentialProvider = [[OBSStaticCredentialProvider alloc] initWithAccessKey:AK secretKey:SK];

//Initialize service configuration.
OBSServiceConfiguration *conf = [[OBSServiceConfiguration alloc] initWithURLString:endPoint credentialProvider:credentialProvider];
    
// Initialize an instance of OBSClient.
client = [[OBSClient alloc] initWithConfiguration:conf];
    
// List parts.
__block NSMutableArray *partsList;
OBSListPartsRequest* listRequest = [[OBSListPartsRequest alloc]initWithBucketName:@"bucketname" objectKey:@"objectname" uploadID:@"uploadID"];
OBSBFTask *listTask = [client listParts:listRequest completionHandler:^(OBSListPartsResponse *response, NSError *error) {
    partsList = [response.partsList mutableCopy];
        
        // Combine parts.
    OBSCompleteMultipartUploadRequest* comRequest = [[OBSCompleteMultipartUploadRequest alloc]initWithBucketName:@"bucketname" objectKey:@"objectname" uploadID:@"uploadID"];
    comRequest.partsList = partsList;
   [client completeMultipartUpload:comRequest completionHandler:^(OBSCompleteMultipartUploadResponse *response, NSError *error) {
            NSLog(@"%@",response);
    }];
        
}];

Aborting a Multipart Upload

After a multipart upload is aborted, you cannot use its upload ID to perform any operation and the uploaded parts will be deleted by OBS.

When an object is being uploaded in multi-part mode or an object fails to be uploaded, parts are generated in the bucket. These parts occupy your storage space. You can cancel the multi-part uploading task to delete unnecessary parts, thereby saving the storage space.

You can call abortMultipartUpload to abort a multipart upload.

static OBSClient *client;
NSString *endPoint = @"your-endpoint";

// Hard-coded or plaintext AK/SK are risky. For security purposes, encrypt your AK/SK and store them in the configuration file or environment variables. In this example, the AK/SK are stored in environment variables for identity authentication. Before running this example, configure environment variables AccessKeyID and SecretAccessKey.
// Obtain an AK/SK pair on the management console. For details, see https://support.huaweicloud.com/intl/en-us/usermanual-ca/ca_01_0003.html.
char* ak_env = getenv("AccessKeyID");
char* sk_env = getenv("SecretAccessKey");
NSString *AK = [NSString stringWithUTF8String:ak_env];
NSString *SK = [NSString stringWithUTF8String:sk_env];

// Initialize identity authentication.
OBSStaticCredentialProvider *credentialProvider = [[OBSStaticCredentialProvider alloc] initWithAccessKey:AK secretKey:SK];
    
//Initialize service configuration.
OBSServiceConfiguration *conf = [[OBSServiceConfiguration alloc] initWithURLString:endPoint credentialProvider:credentialProvider];
    
// Initialize an instance of OBSClient.
client = [[OBSClient alloc] initWithConfiguration:conf];
    
// Abort a multipart upload.
OBSAbortMultipartUploadRequest *abortRequest = [[OBSAbortMultipartUploadRequest alloc] initWithBucketName:@"bucketname" objectKey:@"objectname" uploadID:@"uploadID"];
    
[client abortMultipartUpload:abortRequest completionHandler:^(OBSAbortMultipartUploadResponse *response, NSError *error) {
    NSLog(@"%@",response);
}];

Listing Uploaded Parts

You can call listParts to list successfully uploaded parts of a multipart upload.

The following table describes the parameters involved in this API.

Parameter

Description

Method in OBS iOS SDK

bucketName

Bucket name

request.bucketName

objectKey

Object name

request.objectKey

uploadID

Upload ID, which globally identifies a multipart upload. The value is in the returned result of initiateMultipartUpload.

request.uploadID

maxParts

Maximum number of parts that can be listed per page.

request.maxParts

partNumberMarker

Part number after which listing parts begins. Only parts whose part numbers are larger than this value will be listed.

request.partNumberMarker

  • Listing parts in simple mode
static OBSClient *client;
NSString *endPoint = @"your-endpoint";
NSString *uploadID = @"upload id from OBSInitateMultipartUpload";
    
// Hard-coded or plaintext AK/SK are risky. For security purposes, encrypt your AK/SK and store them in the configuration file or environment variables. In this example, the AK/SK are stored in environment variables for identity authentication. Before running this example, configure environment variables AccessKeyID and SecretAccessKey.
// Obtain an AK/SK pair on the management console. For details, see https://support.huaweicloud.com/intl/en-us/usermanual-ca/ca_01_0003.html.
char* ak_env = getenv("AccessKeyID");
char* sk_env = getenv("SecretAccessKey");
NSString *AK = [NSString stringWithUTF8String:ak_env];
NSString *SK = [NSString stringWithUTF8String:sk_env];

// Initialize identity authentication.
OBSStaticCredentialProvider *credentialProvider = [[OBSStaticCredentialProvider alloc] initWithAccessKey:AK secretKey:SK];
    
//Initialize service configuration.
OBSServiceConfiguration *conf = [[OBSServiceConfiguration alloc] initWithURLString:endPoint credentialProvider:credentialProvider];
    
// Initialize an instance of OBSClient.
client = [[OBSClient alloc] initWithConfiguration:conf];
    
    
OBSListPartsRequest* listRequest = [[OBSListPartsRequest alloc]initWithBucketName:@"bucketname" objectKey:@"objectname" uploadID:uploadID];
[client listParts:listRequest completionHandler:^(OBSListPartsResponse *response, NSError *error) {
    NSLog(@"%@",response);
}];
  • A maximum of 1,000 parts can be listed each time. If the upload of a specified ID contains more than 1,000 parts, response.isTruncated in the response is YES, indicating not all parts were listed. In such case, you can use response.getNextPartNumberMarker to obtain the start position for next listing.
  • If you want to obtain all parts involved in a specific upload ID, you can use the paging mode for listing.
  • Listing all parts

The following sample code lists more than 1,000 parts:

static OBSClient *client;
NSString *endPoint = @"your-endpoint";
NSString *uploadID = @"upload id from OBSInitateMultipartUpload";
    
// Hard-coded or plaintext AK/SK are risky. For security purposes, encrypt your AK/SK and store them in the configuration file or environment variables. In this example, the AK/SK are stored in environment variables for identity authentication. Before running this example, configure environment variables AccessKeyID and SecretAccessKey.
// Obtain an AK/SK pair on the management console. For details, see https://support.huaweicloud.com/intl/en-us/usermanual-ca/ca_01_0003.html.
char* ak_env = getenv("AccessKeyID");
char* sk_env = getenv("SecretAccessKey");
NSString *AK = [NSString stringWithUTF8String:ak_env];
NSString *SK = [NSString stringWithUTF8String:sk_env];

// Initialize identity authentication.
OBSStaticCredentialProvider *credentialProvider = [[OBSStaticCredentialProvider alloc] initWithAccessKey:AK secretKey:SK];
    
//Initialize service configuration.
OBSServiceConfiguration *conf = [[OBSServiceConfiguration alloc] initWithURLString:endPoint credentialProvider:credentialProvider];
    
// Initialize an instance of OBSClient.
client = [[OBSClient alloc] initWithConfiguration:conf];
    
    
__block OBSListPartsResponse *result;
    
OBSListPartsRequest* listRequest = [[OBSListPartsRequest alloc]initWithBucketName:@"bucketname" objectKey:@"objectname" uploadID:uploadID];
    
// List all uploaded parts.
do {
    dispatch_semaphore_t sema = dispatch_semaphore_create(0);
    [client listParts:listRequest completionHandler:^(OBSListPartsResponse *response, NSError *error) {
        result = response;
        NSLog(@"%@",result);
        listRequest.partNumberMarker = result.nextPartNumberMarker;
        dispatch_semaphore_signal(sema);
    }];
    dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
        
} while (result.isTruncated);

  • Listing all parts in paging mode
The previously described listing (1000 parts per page) is a special paging listing mode. The following sample code shows how to specify the number of parts displayed per page when listing.
static OBSClient *client;
NSString *endPoint = @"your-endpoint";
NSString *uploadID = @"upload id from OBSInitateMultipartUpload";
    
// Hard-coded or plaintext AK/SK are risky. For security purposes, encrypt your AK/SK and store them in the configuration file or environment variables. In this example, the AK/SK are stored in environment variables for identity authentication. Before running this example, configure environment variables AccessKeyID and SecretAccessKey.
// Obtain an AK/SK pair on the management console. For details, see https://support.huaweicloud.com/intl/en-us/usermanual-ca/ca_01_0003.html.
char* ak_env = getenv("AccessKeyID");
char* sk_env = getenv("SecretAccessKey");
NSString *AK = [NSString stringWithUTF8String:ak_env];
NSString *SK = [NSString stringWithUTF8String:sk_env];

// Initialize identity authentication.
OBSStaticCredentialProvider *credentialProvider = [[OBSStaticCredentialProvider alloc] initWithAccessKey:AK secretKey:SK];
    
//Initialize service configuration.
OBSServiceConfiguration *conf = [[OBSServiceConfiguration alloc] initWithURLString:endPoint credentialProvider:credentialProvider];
    
// Initialize an instance of OBSClient.
client = [[OBSClient alloc] initWithConfiguration:conf];
    
 __block OBSListPartsResponse *result;
    
OBSListPartsRequest* listRequest = [[OBSListPartsRequest alloc]initWithBucketName:@"bucketname" objectKey:@"objectname" uploadID:uploadID];
listRequest.maxUploads = [NSNumber numberWithInt:100];
// List all uploaded parts.
do {
    dispatch_semaphore_t sema = dispatch_semaphore_create(0);
    [client listParts:listRequest completionHandler:^(OBSListPartsResponse *response, NSError *error) {
       result = response;
        NSLog(@"%@",result);
        listRequest.partNumberMarker = result.nextPartNumberMarker;
        dispatch_semaphore_signal(sema);
    }];
    dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
        
} while (result.isTruncated);

Listing Multipart Uploads

You can call listMultipartUploads to list multipart uploads. The following table describes related parameters.

Parameter

Description

Method in OBS iOS SDK

bucketName

Bucket name

request.bucketName = @"bucketname"

delimiter

Character used to group object names involved in multipart uploads. If the object name contains the delimiter parameter, the character string from the first character to the first delimiter in the object name is grouped under a single result element, commonPrefix. (If a prefix is specified in the request, the prefix must be removed from the object name.)

request.delimiter = @"delimiter"

prefix

Prefix that the object names in the multipart uploads to be listed must contain

request.prefix = @"prefix"

maxUploads

Maximum number of multipart uploads listed in the response body. The value ranges from 1 to 1000. If the value exceeds 1000, only 1,000 multipart uploads are returned.

request.maxUploads = [NSNumber numberWithInt:Int]

keyMarker

Object name to start with when listing multipart uploads

request.keyMarker = @"keymarker"

uploadIDMarker

Upload ID after which the multipart upload listing begins. It is effective only when used with keyMarker so that multipart uploads after uploadIDMarker of keyMarker will be listed.

request.uploadIDMarker = @"ifmarker"

  • Listing multipart uploads in simple mode
static OBSClient *client;
NSString *endPoint = @"your-endpoint";
// Hard-coded or plaintext AK/SK are risky. For security purposes, encrypt your AK/SK and store them in the configuration file or environment variables. In this example, the AK/SK are stored in environment variables for identity authentication. Before running this example, configure environment variables AccessKeyID and SecretAccessKey.
// Obtain an AK/SK pair on the management console. For details, see https://support.huaweicloud.com/intl/en-us/usermanual-ca/ca_01_0003.html.
char* ak_env = getenv("AccessKeyID");
char* sk_env = getenv("SecretAccessKey");
NSString *AK = [NSString stringWithUTF8String:ak_env];
NSString *SK = [NSString stringWithUTF8String:sk_env];

// Initialize identity authentication.
OBSStaticCredentialProvider *credentialProvider = [[OBSStaticCredentialProvider alloc] initWithAccessKey:AK secretKey:SK];
    
//Initialize service configuration.
OBSServiceConfiguration *conf = [[OBSServiceConfiguration alloc] initWithURLString:endPoint credentialProvider:credentialProvider];
    
// Initialize an instance of OBSClient.
client = [[OBSClient alloc] initWithConfiguration:conf];
    
// List multipart uploads.
OBSListMultipartUploadsRequest *request = [[OBSListMultipartUploadsRequest alloc]initWithBucketName:@"bucketname"];
    
[client listMultipartUploads:request completionHandler:^(OBSListMultipartUploadsResponse *response, NSError *error) {
    NSLog(@"%@",response);
}];
  • Information about a maximum of 1000 multipart uploads can be listed each time. If a bucket contains more than 1000 multipart uploads and response.isTruncated is YES, not all uploads are listed. In such cases, you can use response.nextKeyMarker and response.nextUploadIdMarker to obtain the start position for next listing.
  • If you want to obtain all multipart uploads in a bucket, you can list them in paging mode.
  • Listing all multipart uploads
static OBSClient *client;
NSString *endPoint = @"your-endpoint";
// Hard-coded or plaintext AK/SK are risky. For security purposes, encrypt your AK/SK and store them in the configuration file or environment variables. In this example, the AK/SK are stored in environment variables for identity authentication. Before running this example, configure environment variables AccessKeyID and SecretAccessKey.
// Obtain an AK/SK pair on the management console. For details, see https://support.huaweicloud.com/intl/en-us/usermanual-ca/ca_01_0003.html.
char* ak_env = getenv("AccessKeyID");
char* sk_env = getenv("SecretAccessKey");
NSString *AK = [NSString stringWithUTF8String:ak_env];
NSString *SK = [NSString stringWithUTF8String:sk_env];
    
// Initialize identity authentication.
OBSStaticCredentialProvider *credentialProvider = [[OBSStaticCredentialProvider alloc] initWithAccessKey:AK secretKey:SK];
    
//Initialize service configuration.
OBSServiceConfiguration *conf = [[OBSServiceConfiguration alloc] initWithURLString:endPoint credentialProvider:credentialProvider];
    
// Initialize an instance of OBSClient.
client = [[OBSClient alloc] initWithConfiguration:conf];
__block OBSListMultipartUploadsResponse *result;
OBSListMultipartUploadsRequest *request = [[OBSListMultipartUploadsRequest alloc]initWithBucketName:@"bucket-ios-test03"];
    
//List all multipart uploads.
do {
    dispatch_semaphore_t sema = dispatch_semaphore_create(0);
    [client listMultipartUploads:request completionHandler:^(OBSListMultipartUploadsResponse *response, NSError *error) {
        result = response;
        NSLog(@"%@",result);
        request.keyMarker = result.nextKeyMarker;
        request.uploadIDMarker = result.nextUploadIDMarker;
        dispatch_semaphore_signal(sema);
        }];
    dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
} while (result.isTruncated);

  • Listing all multipart uploads in paging mode

The previous sample code (listing 1000 uploads per page) shows a special paging listing mode. The following sample code shows how to specify the number of uploads displayed per page when listing.

static OBSClient *client;
NSString *endPoint = @"your-endpoint";
// Hard-coded or plaintext AK/SK are risky. For security purposes, encrypt your AK/SK and store them in the configuration file or environment variables. In this example, the AK/SK are stored in environment variables for identity authentication. Before running this example, configure environment variables AccessKeyID and SecretAccessKey.
// Obtain an AK/SK pair on the management console. For details, see https://support.huaweicloud.com/intl/en-us/usermanual-ca/ca_01_0003.html.
char* ak_env = getenv("AccessKeyID");
char* sk_env = getenv("SecretAccessKey");
NSString *AK = [NSString stringWithUTF8String:ak_env];
NSString *SK = [NSString stringWithUTF8String:sk_env];
    
// Initialize identity authentication.
OBSStaticCredentialProvider *credentialProvider = [[OBSStaticCredentialProvider alloc] initWithAccessKey:AK secretKey:SK];
    
//Initialize service configuration.
OBSServiceConfiguration *conf = [[OBSServiceConfiguration alloc] initWithURLString:endPoint credentialProvider:credentialProvider];
    
// Initialize an instance of OBSClient.
client = [[OBSClient alloc] initWithConfiguration:conf];
    
    
__block OBSListMultipartUploadsResponse *result;
    
    
OBSListMultipartUploadsRequest *request = [[OBSListMultipartUploadsRequest alloc]initWithBucketName:@"bucketname"];
    
// Set the number of multipart uploads displayed per page to 100.
request.maxUploads = [NSNumber numberWithInt:100];
    
//List all multipart uploads.
do {
    dispatch_semaphore_t sema = dispatch_semaphore_create(0);
    [client listMultipartUploads:request completionHandler:^(OBSListMultipartUploadsResponse *response, NSError *error) {
        result = response;
        NSLog(@"%@",result);
        request.keyMarker = result.nextKeyMarker;
        request.uploadIDMarker = result.nextUploadIDMarker;
        dispatch_semaphore_signal(sema);
            
    }];
    dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
        
} while (result.isTruncated);