All Products
Search
Document Center

Object Storage Service:Resumable upload (iOS SDK)

Last Updated:Mar 20, 2026

Resumable upload lets you recover a failed large-file upload from where it stopped, so you don't have to restart from the beginning after a network interruption.

Prerequisites

Before you begin, ensure that you have:

The bucket region is determined by the endpoint you specified during initialization.

Usage notes

  • Resumable upload supports local files only.

  • For objects smaller than 5 GB uploaded from a mobile device, use simple upload instead. Resumable upload is built on multipart upload and requires multiple network requests, making it inefficient for smaller objects.

  • Each part's integrity is verified using MD5 by default. You don't need to set the Content-MD5 header.

  • Resumable upload supports the upload callback feature, used the same way as in simple upload. For details, see Callback.

  • If you use Security Token Service (STS) for authentication, make sure you are authorized to call all five API operations listed below.

  • Incomplete multipart uploads accumulate in OSS if upload tasks are abandoned. Set lifecycle rules on the bucket to periodically clean them up. For details, see Lifecycle management.

How it works

Resumable upload is built on OSS multipart upload. The iOS SDK calls the following API operations internally:

API operationDescription
InitMultipartUploadInitializes the multipart upload and returns an upload ID
UploadPartUploads individual parts
ListPartsLists uploaded parts
CompleteMultipartUploadCombines all parts into the final object
AbortMultipartUploadCancels the upload and removes uploaded parts

When you specify a directory for the checkpoint file, the SDK saves upload progress locally. If the upload fails, the next call to resumableUpload reads the checkpoint file and resumes from the last successful part rather than restarting.

Upload an object with resumable upload

The following example uploads a local file using OSSResumableUploadRequest. It saves the checkpoint file to the system caches directory so the upload can resume after a failure.

// Initialize the request
OSSResumableUploadRequest *resumableUpload = [OSSResumableUploadRequest new];
resumableUpload.bucketName = <bucketName>;
// objectKey is the full path of the object in OSS, including the file extension.
// Example: images/photos/2024/photo.jpg
resumableUpload.objectKey = <objectKey>;

// Set the part size (1 MB by default)
resumableUpload.partSize = 1024 * 1024;

// Save checkpoint files to the system caches directory.
// If the upload fails, the next call resumes from the last checkpoint.
NSString *cachesDir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
resumableUpload.recordDirectoryPath = cachesDir;

// Set deleteUploadIdOnCancelling to NO so the checkpoint file is kept when
// the upload is cancelled. This allows the upload to resume later.
// The default is YES, which deletes the checkpoint file on cancellation.
resumableUpload.deleteUploadIdOnCancelling = NO;

// Track upload progress
resumableUpload.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) {
    NSLog(@"Sent: %lld  Total sent: %lld  Expected: %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);
};

resumableUpload.uploadingFileURL = [NSURL fileURLWithPath:<your-file-path>];

OSSTask *resumeTask = [client resumableUpload:resumableUpload];
[resumeTask continueWithBlock:^id(OSSTask *task) {
    if (task.error) {
        NSLog(@"Upload failed: %@", task.error);
        if ([task.error.domain isEqualToString:OSSClientErrorDomain] &&
            task.error.code == OSSClientErrorCodeCannotResumeUpload) {
            // The upload cannot be resumed. Start a new upload with a fresh request.
        }
    } else {
        NSLog(@"Upload succeeded.");
    }
    return nil;
}];

// Uncomment to wait synchronously:
// [resumeTask waitUntilFinished];

Replace the following placeholders:

PlaceholderDescription
<bucketName>The name of your OSS bucket
<objectKey>The full path of the object in OSS, for example, videos/upload/sample.mp4
<your-file-path>The absolute path of the local file, for example, /var/mobile/Documents/sample.mp4
After a successful upload, the checkpoint file is deleted automatically. If you don't set recordDirectoryPath, checkpoint records are not saved and the entire upload restarts on failure.

Cancel and resume an upload

Cancel an upload

Call cancel on the upload task to stop it.

[resumableUpload cancel];

By default (deleteUploadIdOnCancelling = YES), the checkpoint file is deleted when an upload is cancelled. The next upload of the same object starts from the beginning.

To keep the checkpoint file so the upload can resume later, set deleteUploadIdOnCancelling = NO before starting the upload (shown in the example above).

Important

When you cancel an upload with deleteUploadIdOnCancelling = YES, the parts already uploaded to OSS are deleted. To keep those parts and resume the upload later, set deleteUploadIdOnCancelling = NO and specify recordDirectoryPath. If a lifecycle rule deletes the parts from OSS before you resume, the checkpoint file on the device becomes invalid.

Resume a cancelled upload

To resume an upload that was cancelled with deleteUploadIdOnCancelling = NO, create a new OSSResumableUploadRequest with the same bucketName, objectKey, and recordDirectoryPath. The SDK reads the existing checkpoint file and resumes from the last successful part.

OSSResumableUploadRequest *resumableUpload = [OSSResumableUploadRequest new];
resumableUpload.bucketName = <bucketName>;
resumableUpload.objectKey = <objectKey>;
resumableUpload.partSize = 1024 * 1024;

NSString *cachesDir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
resumableUpload.recordDirectoryPath = cachesDir;  // Must match the original path
resumableUpload.deleteUploadIdOnCancelling = NO;

resumableUpload.uploadingFileURL = [NSURL fileURLWithPath:<your-file-path>];

OSSTask *resumeTask = [client resumableUpload:resumableUpload];
[resumeTask continueWithBlock:^id(OSSTask *task) {
    if (task.error) {
        NSLog(@"Resume failed: %@", task.error);
    } else {
        NSLog(@"Upload succeeded.");
    }
    return nil;
}];

What's next

  • Callback — Use upload callback to receive notifications after an upload completes.

  • Lifecycle management — Set lifecycle rules to automatically clean up incomplete multipart uploads.