In a wireless network environment, it takes a long time to upload a large object and the upload may fail due to poor network connectivity or network switchover. If the upload fails, the entire object must be uploaded again. To resolve this issue, Object Storage Service (OSS) SDK for Android provides the resumable upload feature.

Background information

We recommend that you do not use resumable upload when you upload objects smaller than 5 GB in size from a mobile device. Resumable upload is implemented by using the multipart upload method. Resumable upload of a single object requires multiple network requests, which is inefficient. The following section provides the precautions you need to understand before and during resumable upload.

  • Before resumable upload

    Before you upload an object to OSS by using the resumable upload method, you can specify a folder for the checkpoint file that stores resumable upload records. The checkpoint file applies only to the current resumable upload task.

    • If you do not specify the folder for the checkpoint file and part of a large object fails to be uploaded due to network issues, it takes a large amount of time and consumes a large amount of traffic to upload the entire large object again.
    • If you specify the folder for the checkpoint file, a failed resumable upload task can be resumed from the position recorded in the checkpoint file.
  • During resumable upload

    When you use resumable upload, you must understand the following information:

    • Resumable upload allows you to upload only local files. Resumable upload supports upload callback. You can use resumable upload in a similar way you use upload callback. For more information, see Callback.
    • Resumable upload is implemented by calling the following API operations: InitMultipartUpload, UploadPart, ListParts, CompleteMultipartUpload, and AbortMultipartUpload. If you want to use the STS authentication mode to perform resumable upload tasks, make sure that you are authorized to call the preceding API operations.
    • By default, the MD5 hash of each part is verified in a resumable upload task. Therefore, you do not need to specify the Content-Md5 header in the request.
    • When a resumable upload task fails, the uploaded parts become unnecessary in OSS. To resolve this issue, you can configure lifecycle rules for the bucket that contains the parts to clear the parts on a regular basis. For more information, see Configure lifecycle rules.

Examples

You can use resumable upload to upload a local file to OSS in synchronous or asynchronous mode.

  • Call the synchronous API operation to upload a local file by using resumable upload

    The following code provides an example on how to use resumable upload in synchronous mode to upload a local file named examplefile.txt to the exampledir directory in examplebucket. After the local file is uploaded, the object is named exampleobject.txt. The checkpoint file is stored in your computer.

    // Specify the name of the bucket. Example: examplebucket. 
    String bucketName = "examplebucket";
    // Specify the full path of the object. Example: exampledir/exampleobject.txt. The full path of the object cannot contain bucket names. 
    String objectName = "exampledir/exampleobject.txt";
    // Specify the full path of the local file. Example: /storage/emulated/0/oss/examplefile.txt. 
    String localFilepath = "/storage/emulated/0/oss/examplefile.txt";
    
    String recordDirectory = Environment.getExternalStorageDirectory().getAbsolutePath() + "/oss_record/";
    
    File recordDir = new File(recordDirectory);
    
    // Make sure that the folder for the checkpoint file exists. If the folder does not exist, create a folder. 
    if (!recordDir.exists()) {
        recordDir.mkdirs();
    }
    
    // Create a resumable upload request and specify the absolute path of the checkpoint file. 
    ResumableUploadRequest request = new ResumableUploadRequest(bucketName, objectName, localFilepath, recordDirectory);
    // Set the DeleteUploadOnCancelling parameter when the OSSAsyncTask cancel() method is called. When this parameter is set to false, the checkpoint file is retained. If you do not specify this parameter, default value true is used, which indicates that the checkpoint file is deleted. The entire object is uploaded again during the next upload. 
    request.setDeleteUploadOnCancelling(false);
    // Configure upload callback. 
    request.setProgressCallback(new OSSProgressCallback<ResumableUploadRequest>() {
        @Override
        public void onProgress(ResumableUploadRequest request, long currentSize, long totalSize) {
            Log.d("resumableUpload", "currentSize: " + currentSize + " totalSize: " + totalSize);
        }
    });
    
    
    ResumableUploadResult uploadResult = oss.resumableUpload(request);

    If you use Android 10 or later for partitioned storage, you can use the Uniform Resource Identifier (URI) of the local file to upload the file to OSS.

    // Specify the name of the bucket. Example: examplebucket. 
    String bucketName = "examplebucket";
    // Specify the full path of the object. Example: exampledir/exampleobject.txt. The full path of the object cannot contain bucket names. 
    String objectName = "exampledir/exampleobject.txt";
    
    String recordDirectory = getApplication().getFilesDir().getAbsolutePath() + "/oss_record/";
    
    File recordDir = new File(recordDirectory);
    
    // Make sure that the folder for the checkpoint file exists. If the folder does not exist, create a folder. 
    if (!recordDir.exists()) {
        recordDir.mkdirs();
    }
    
    // Create a resumable upload request and specify the absolute path of the checkpoint file. 
    ResumableUploadRequest request = new ResumableUploadRequest(bucketName, objectName, fileUri, recordDirectory);
    // Set the DeleteUploadOnCancelling parameter when the OSSAsyncTask cancel() method is called. When this parameter is set to false, the checkpoint file is retained. If you do not specify this parameter, default value true is used, which indicates that the checkpoint file is deleted. The entire object is uploaded again during the next upload. 
    request.setDeleteUploadOnCancelling(false);
    // Configure upload callback. 
    request.setProgressCallback(new OSSProgressCallback<ResumableUploadRequest>() {
        @Override
        public void onProgress(ResumableUploadRequest request, long currentSize, long totalSize) {
            Log.d("resumableUpload", "currentSize: " + currentSize + " totalSize: " + totalSize);
        }
    });
    
    
    ResumableUploadResult uploadResult = oss.resumableUpload(request);

    The following code provides an example on how to implement resumable upload without storing the checkpoint file in your computer:

    // Specify the name of the bucket. Example: examplebucket. 
    String bucketName = "examplebucket";
    // Specify the full path of the object. Example: exampledir/exampleobject.txt. The full path of the object cannot contain bucket names. 
    String objectName = "exampledir/exampleobject.txt";
    // Specify the full path of the local file. Example: /storage/emulated/0/oss/examplefile.txt. 
    String localFilepath = "/storage/emulated/0/oss/examplefile.txt";
    
    // Create a resumable upload request. 
    ResumableUploadRequest request = new ResumableUploadRequest(bucketName, objectName, localFilepath);
    // Set the DeleteUploadOnCancelling parameter when the OSSAsyncTask cancel() method is called. When this parameter is set to false, the checkpoint file is retained. If you do not specify this parameter, default value true is used, which indicates that the checkpoint file is deleted. The entire object is uploaded again during the next upload. 
    request.setDeleteUploadOnCancelling(false);
    // Configure upload callback. 
    request.setProgressCallback(new OSSProgressCallback<ResumableUploadRequest>() {
        @Override
        public void onProgress(ResumableUploadRequest request, long currentSize, long totalSize) {
            Log.d("resumableUpload", "currentSize: " + currentSize + " totalSize: " + totalSize);
        }
    });
    
    
    ResumableUploadResult uploadResult = oss.resumableUpload(request);
  • Call the asynchronous API operation to upload a local file by using resumable upload

    The following code provides an example on how to use resumable upload in asynchronous mode to upload a local file named examplefile.txt to the exampledir directory in examplebucket. After the local file is uploaded, the object is named exampleobject.txt. The checkpoint file is stored in your computer.

    // Specify the name of the bucket. Example: examplebucket. 
    String bucketName = "examplebucket";
    // Specify the full path of the object. Example: exampledir/exampleobject.txt. The full path of the object cannot contain bucket names. 
    String objectName = "exampledir/exampleobject.txt";
    // Specify the full path of the local file. Example: /storage/emulated/0/oss/examplefile.txt. 
    String localFilepath = "/storage/emulated/0/oss/examplefile.txt";
    String recordDirectory = Environment.getExternalStorageDirectory().getAbsolutePath() + "/oss_record/";
    
    File recordDir = new File(recordDirectory);
    
    // Make sure that the folder for the checkpoint file exists. If the folder does not exist, create a folder. 
    if (!recordDir.exists()) {
        recordDir.mkdirs();
    }
    
    // Create a resumable upload request and specify the absolute path of the checkpoint file. 
    ResumableUploadRequest request = new ResumableUploadRequest(bucketName, objectName, localFilepath, recordDirectory);
    // Configure upload callback. 
    request.setProgressCallback(new OSSProgressCallback<ResumableUploadRequest>() {
        @Override
        public void onProgress(ResumableUploadRequest request, long currentSize, long totalSize) {
            Log.d("resumableUpload", "currentSize: " + currentSize + " totalSize: " + totalSize);
        }
    });
    
    
    OSSAsyncTask resumableTask = oss.asyncResumableUpload(request, new OSSCompletedCallback<ResumableUploadRequest, ResumableUploadResult>() {
        @Override
        public void onSuccess(ResumableUploadRequest request, ResumableUploadResult result) {
            Log.d("resumableUpload", "success!");
        }
    
        @Override
        public void onFailure(ResumableUploadRequest request, ClientException clientExcepion, ServiceException serviceException) {
            // Handle exceptions. 
        }
    });
    
    // Wait until the resumable upload task is complete. 
    resumableTask.waitUntilFinished();                

    If you use Android 10 or later for partitioned storage, you can use the URI of the local file to upload the file to OSS.

    // Specify the name of the bucket. Example: examplebucket. 
    String bucketName = "examplebucket";
    // Specify the full path of the object. Example: exampledir/exampleobject.txt. The full path of the object cannot contain bucket names. 
    String objectName = "exampledir/exampleobject.txt";
    String recordDirectory = getApplication().getFilesDir().getAbsolutePath() + "/oss_record/";
    
    File recordDir = new File(recordDirectory);
    
    // Make sure that the folder for the checkpoint file exists. If the folder does not exist, create a folder. 
    if (!recordDir.exists()) {
        recordDir.mkdirs();
    }
    
    // Create a resumable upload request and specify the absolute path of the checkpoint file. 
    ResumableUploadRequest request = new ResumableUploadRequest(bucketName, objectName, fileUri, recordDirectory);
    // Set the DeleteUploadOnCancelling parameter when the OSSAsyncTask cancel() method is called. When this parameter is set to false, the checkpoint file is retained. If you do not specify this parameter, default value true is used, which indicates that the checkpoint file is deleted. The entire object is uploaded again during the next upload. 
    request.setDeleteUploadOnCancelling(false);
    // Configure upload callback. 
    request.setProgressCallback(new OSSProgressCallback<ResumableUploadRequest>() {
        @Override
        public void onProgress(ResumableUploadRequest request, long currentSize, long totalSize) {
            Log.d("resumableUpload", "currentSize: " + currentSize + " totalSize: " + totalSize);
        }
    });
    
    
    OSSAsyncTask resumableTask = oss.asyncResumableUpload(request, new OSSCompletedCallback<ResumableUploadRequest, ResumableUploadResult>() {
        @Override
        public void onSuccess(ResumableUploadRequest request, ResumableUploadResult result) {
            Log.d("resumableUpload", "success!");
        }
    
        @Override
        public void onFailure(ResumableUploadRequest request, ClientException clientExcepion, ServiceException serviceException) {
            // Handle exceptions. 
        }
    });
    
    // Wait until the resumable upload task is complete. 
    resumableTask.waitUntilFinished();

    The following code provides an example on how to implement resumable upload without storing the checkpoint file in your computer:

    // Specify the name of the bucket. Example: examplebucket. 
    String bucketName = "examplebucket";
    // Specify the full path of the object. Example: exampledir/exampleobject.txt. The full path of the object cannot contain bucket names. 
    String objectName = "exampledir/exampleobject.txt";
    // Specify the full path of the local file. Example: /storage/emulated/0/oss/examplefile.txt. 
    String localFilepath = "/storage/emulated/0/oss/examplefile.txt";
    
    // Create a resumable upload request. 
    ResumableUploadRequest request = new ResumableUploadRequest(bucketName, objectName, localFilepath);
    
    // Configure upload callback. 
    request.setProgressCallback(new OSSProgressCallback<ResumableUploadRequest>() {
        @Override
        public void onProgress(ResumableUploadRequest request, long currentSize, long totalSize) {
            Log.d("resumableUpload", "currentSize: " + currentSize + " totalSize: " + totalSize);
        }
    });
    // Call the asyncResumableUpload method to perform the resumable upload task. 
    OSSAsyncTask resumableTask = oss.asyncResumableUpload(request, new OSSCompletedCallback<ResumableUploadRequest, ResumableUploadResult>() {
        @Override
        public void onSuccess(ResumableUploadRequest request, ResumableUploadResult result) {
            Log.d("resumableUpload", "success!");
        }
    
        @Override
        public void onFailure(ResumableUploadRequest request, ClientException clientExcepion, ServiceException serviceException) {
            // Handle exceptions. 
        }
    });
    
    // Wait until the resumable upload task is complete. 
    resumableTask.waitUntilFinished();