edit-icon download-icon

Multipart upload

Last Updated: Dec 26, 2017

The following describes the procedure of uploading files with multipart upload.

Initialize multipart upload

  1. __block NSString * uploadId = nil;
  2. __block NSMutableArray * partInfos = [NSMutableArray new];
  3. NSString * uploadToBucket = @"<bucketName>";
  4. NSString * uploadObjectkey = @"<objectKey>";
  5. OSSInitMultipartUploadRequest * init = [OSSInitMultipartUploadRequest new];
  6. init.bucketName = uploadToBucket;
  7. init.objectKey = uploadObjectkey;
  8. // init.contentType = @"application/octet-stream";
  9. OSSTask * initTask = [client multipartUploadInit:init];
  10. [initTask waitUntilFinished];
  11. if (!initTask.error) {
  12. OSSInitMultipartUploadResult * result = initTask.result;
  13. uploadId = result.uploadId;
  14. } else {
  15. NSLog(@"multipart upload failed, error: %@", initTask.error);
  16. return;
  17. }
  • Here, OSSInitMultipartUploadRequest is used to specify the name of the file to be uploaded and the bucket it belongs to.
  • The result returned by multipartUploadInit contains an UploadId, which uniquely identifies a multipart upload event and is used in the next sections.

Upload parts

  1. NSString * filePath = [docDir stringByAppendingPathComponent:@"***"];
  2. //The file to upload
  3. int chuckCount = *;
  4. //Number of multipart uploads
  5. uint64_t offset = fileSie/chuckCount;
  6. //Part size
  7. for (int i = 1; i <= chuckCount; i++) {
  8. OSSUploadPartRequest * uploadPart = [OSSUploadPartRequest new];
  9. uploadPart.bucketName = uploadToBucket;
  10. uploadPart.objectkey = uploadObjectkey;
  11. uploadPart.uploadId = uploadId;
  12. uploadPart.partNumber = i; // part number start from 1
  13. NSFileHandle* readHandle = [NSFileHandle fileHandleForReadingAtPath:filePath];
  14. [readHandle seekToFileOffset:offset * (i -1)];
  15. NSData* data = [readHandle readDataOfLength:offset];
  16. uploadPart.uploadPartData = data;
  17. OSSTask * uploadPartTask = [client uploadPart:uploadPart];
  18. [uploadPartTask waitUntilFinished];
  19. if (!uploadPartTask.error) {
  20. OSSUploadPartResult * result = uploadPartTask.result;
  21. uint64_t fileSize = [[[NSFileManager defaultManager] attributesOfItemAtPath:uploadPart.uploadPartFileURL.absoluteString error:nil] fileSize];
  22. [partInfos addObject:[OSSPartInfo partInfoWithPartNum:i eTag:result.eTag size:fileSize]];
  23. } else {
  24. NSLog(@"upload part error: %@", uploadPartTask.error);
  25. return;
  26. }
  27. }

The preceding code shows how to call uploadPart to upload each part. Note:

  • An UploadID and a PartNum must be specified for each multipart upload request.
  • The UploadPart requires that, except for the last part, all other part sizes be greater than 100 KB. But the Upload Part API does not immediately verify the size (because you do not know whether it is the last one). It is only verified when you complete multipart upload.
  • Part numbers range from 1 to 10000. If this range is exceeded, OSS returns an InvalidArgument error code.
  • Be sure to position the stream to the beginning of the part each time a part is to be uploaded.
  • Each time a part is uploaded, the result returned by OSS contains the ETag of the part, the value of which is the MD5 value of the part. Combine it with the block number into a partEtag and store it for later use in completing multipart upload.

Configure the MD5 verification

OSS provides an end-to-end file verification feature to handle the complexities in mobile network environments. To check whether the file uploaded to OSS with multipart upload is consistent with the local file, add the Content-MD5 value to the file during the uploading and then the OSS server performs the MD5 verification. The uploading can be successful only when the MD5 value of the file received by the OSS server is equal to the Content-MD5 value, thus guaranteeing the consistency of uploaded file.

  1. OSSUploadPartRequest * uploadPart = [OSSUploadPartRequest new];
  2. uploadPart.bucketName = TEST_BUCKET;
  3. uploadPart.uploadId = uploadId;
  4. ....
  5. uploadPart.contentMd5 = [OSSUtil fileMD5String:filepath];

Complete multipart upload

In the following code, “partInfos” refers to the list of partETags saved during the multipart upload. After OSS receives the part list submitted by the user, it verifies the validity of each data part one by one. When all the data parts are verified to be valid, OSS combines them into a complete file.

  1. OSSCompleteMultipartUploadRequest * complete = [OSSCompleteMultipartUploadRequest new];
  2. complete.bucketName = uploadToBucket;
  3. complete.objectKey = uploadObjectkey;
  4. complete.uploadId = uploadId;
  5. complete.partInfos = partInfos;
  6. OSSTask * completeTask = [client completeMultipartUpload:complete];
  7. [[completeTask continueWithBlock:^id(OSSTask *task) {
  8. if (!task.error) {
  9. OSSCompleteMultipartUploadResult * result = task.result;
  10. // ...
  11. } else {
  12. // ...
  13. }
  14. return nil;
  15. }] waitUntilFinished];

Complete multipart upload (set ServerCallback)

You can set the Server Callback parameter when completing the multipart upload request. A callback request is sent to the specified server address after the upload request is complete. See result.serverReturnJsonString for the servercallback result.

  1. OSSCompleteMultipartUploadRequest * complete = [OSSCompleteMultipartUploadRequest new];
  2. complete.bucketName = @"<bucketName>";
  3. complete.objectKey = @"<objectKey>";
  4. complete.uploadId = uploadId;
  5. complete.partInfos = partInfos;
  6. complete.callbackParam = @{
  7. @"callbackUrl": @"<server address>",
  8. @"callbackBody": @"<test>"
  9. };
  10. complete.callbackVar = @{
  11. @"var1": @"value1",
  12. @"var2": @"value2"
  13. };
  14. OSSTask * completeTask = [client completeMultipartUpload:complete];
  15. [[completeTask continueWithBlock:^id(OSSTask *task) {
  16. if (!task.error) {
  17. OSSCompleteMultipartUploadResult * result = task.result;
  18. NSLog(@"server call back return : %@", result.serverReturnJsonString);
  19. } else {
  20. // ...
  21. }
  22. return nil;
  23. }] waitUntilFinished];

Delete a multipart upload event

The following code cancels a multipart upload request mapped to a specified UploadID.

  1. OSSAbortMultipartUploadRequest * abort = [OSSAbortMultipartUploadRequest new];
  2. abort.bucketName = @"<bucketName>";
  3. abort.objectKey = @"<objectKey>";
  4. abort.uploadId = uploadId;
  5. OSSTask * abortTask = [client abortMultipartUpload:abort];
  6. [abortTask waitUntilFinished];
  7. if (!abortTask.error) {
  8. OSSAbortMultipartUploadResult * result = abortTask.result;
  9. uploadId = result.uploadId;
  10. } else {
  11. NSLog(@"multipart upload failed, error: %@", abortTask.error);
  12. return;
  13. }

List parts

Call the listParts method to obtain all the uploaded parts of an upload event.

  1. OSSListPartsRequest * listParts = [OSSListPartsRequest new];
  2. listParts.bucketName = @"<bucketName>";
  3. listParts.objectKey = @"<objectkey>";
  4. listParts.uploadId = @"<uploadid>";
  5. OSSTask * listPartTask = [client listParts:listParts];
  6. [listPartTask continueWithBlock:^id(OSSTask *task) {
  7. if (!task.error) {
  8. NSLog(@"list part result success!");
  9. OSSListPartsResult * listPartResult = task.result;
  10. for (NSDictionary * partInfo in listPartResult.parts) {
  11. NSLog(@"each part: %@", partInfo);
  12. }
  13. } else {
  14. NSLog(@"list part result error: %@", task.error);
  15. }
  16. return nil;
  17. }];

Note: By default, if the bucket has more than 1000 multipart upload events, only 1000 of them are returned with IsTruncated shown as False in the returned result, and NextPartNumberMarker is returned as the starting point for next read.

Thank you! We've received your feedback.