All Products
Search
Document Center

Object Storage Service:Obtain the upload progress during object upload

Last Updated:Mar 20, 2026

OSS SDKs expose a progress callback that fires periodically during a PutObject upload, reporting bytes transferred and the total object size. Use these values to update a progress bar or log transfer status in your application.

The examples on this page apply to PutObject. To track progress for multipart uploads or other upload operations, see Overview.

How it works

Each SDK delivers progress through a language-native mechanism — a listener interface, a callback function, or an event — that the SDK invokes at regular intervals during the upload. The callback receives:

ParameterDescription
Bytes transferred this intervalThe incremental chunk size since the last callback invocation
Total bytes transferredCumulative bytes sent so far
Total object sizeFull size of the object being uploaded. May be None, -1, or unknown if the size cannot be determined before the upload starts

Use OSS SDKs

Java

Implement the ProgressListener interface and attach it to PutObjectRequest using withProgressListener(). The SDK fires ProgressEvent events as the upload proceeds.

The progressChanged() method handles five event types:

Event typeMeaning
TRANSFER_STARTED_EVENTUpload has started
REQUEST_CONTENT_LENGTH_EVENTTotal object size is now known
REQUEST_BYTE_TRANSFER_EVENTA chunk has been sent; update the running byte count
TRANSFER_COMPLETED_EVENTUpload finished successfully
TRANSFER_FAILED_EVENTUpload failed
import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.event.ProgressEvent;
import com.aliyun.oss.event.ProgressEventType;
import com.aliyun.oss.event.ProgressListener;
import com.aliyun.oss.model.PutObjectRequest;
import java.io.File;

public class PutObjectProgressListenerDemo implements ProgressListener {
    private long bytesWritten = 0;
    private long totalBytes = -1;
    private boolean succeed = false;

    public static void main(String[] args) throws Exception {
        // Specify the endpoint of the region where your bucket is located.
        // Example: https://oss-cn-hangzhou.aliyuncs.com
        String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
        // Read credentials from environment variables.
        // Set OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET before running.
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
        String bucketName = "examplebucket";
        String objectName = "exampledir/exampleobject.txt";
        String pathName = "D:\\localpath\\examplefile.txt";
        String region = "cn-hangzhou";

        ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
        clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);
        OSS ossClient = OSSClientBuilder.create()
            .endpoint(endpoint)
            .credentialsProvider(credentialsProvider)
            .clientConfiguration(clientBuilderConfiguration)
            .region(region)
            .build();

        try {
            // Attach the progress listener to the upload request.
            ossClient.putObject(new PutObjectRequest(bucketName, objectName, new File(pathName)).
                    <PutObjectRequest>withProgressListener(new PutObjectProgressListenerDemo()));
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }

    public boolean isSucceed() {
        return succeed;
    }

    @Override
    public void progressChanged(ProgressEvent progressEvent) {
        long bytes = progressEvent.getBytes();
        ProgressEventType eventType = progressEvent.getEventType();
        switch (eventType) {
            case TRANSFER_STARTED_EVENT:
                System.out.println("Start to upload......");
                break;
            case REQUEST_CONTENT_LENGTH_EVENT:
                this.totalBytes = bytes;
                System.out.println(this.totalBytes + " bytes in total will be uploaded to OSS");
                break;
            case REQUEST_BYTE_TRANSFER_EVENT:
                this.bytesWritten += bytes;
                if (this.totalBytes != -1) {
                    int percent = (int)(this.bytesWritten * 100.0 / this.totalBytes);
                    System.out.println(bytes + " bytes have been written at this time, upload progress: " + percent + "%(" + this.bytesWritten + "/" + this.totalBytes + ")");
                } else {
                    System.out.println(bytes + " bytes have been written at this time, upload ratio: unknown" + "(" + this.bytesWritten + "/...)");
                }
                break;
            case TRANSFER_COMPLETED_EVENT:
                this.succeed = true;
                System.out.println("Succeed to upload, " + this.bytesWritten + " bytes have been transferred in total");
                break;
            case TRANSFER_FAILED_EVENT:
                System.out.println("Failed to upload, " + this.bytesWritten + " bytes have been transferred");
                break;
            default:
                break;
        }
    }
}

Python

Pass a progress_callback function to put_object(). The SDK calls it with consumed_bytes and total_bytes as the upload proceeds.

total_bytes is None if the object size cannot be determined before the upload starts. Always guard against this before calculating a percentage.

# -*- coding: utf-8 -*-
from __future__ import print_function
import sys
import oss2
from oss2.credentials import EnvironmentVariableCredentialsProvider

# Read credentials from environment variables.
# Set OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET before running.
auth = oss2.ProviderAuthV4(EnvironmentVariableCredentialsProvider())

# Specify the endpoint of the region where your bucket is located.
endpoint = "https://oss-cn-hangzhou.aliyuncs.com"

# Specify the region ID that maps to the endpoint.
# Required when using signature algorithm V4.
region = "cn-hangzhou"

bucket = oss2.Bucket(auth, endpoint, "examplebucket", region=region)

def percentage(consumed_bytes, total_bytes):
    # total_bytes is None when the object size is unknown before the upload starts.
    if total_bytes:
        rate = int(100 * (float(consumed_bytes) / float(total_bytes)))
        print('\r{0}% '.format(rate), end='')
        sys.stdout.flush()

bucket.put_object('exampledir/exampleobject.txt', 'a'*1024*1024, progress_callback=percentage)

.NET

Subscribe to the StreamTransferProgress event on PutObjectRequest. The event handler receives a StreamTransferProgressArgs argument with TransferredBytes and TotalBytes.

using System;
using System.IO;
using Aliyun.OSS;
using Aliyun.OSS.Common;

namespace PutObjectProgress
{
    class Program
    {
        static void Main(string[] args)
        {
            Program.PutObjectProgress();
            Console.ReadKey();
        }

        public static void PutObjectProgress()
        {
            // Specify the endpoint of the region where your bucket is located.
            // Example: https://oss-cn-hangzhou.aliyuncs.com
            var endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
            // Read credentials from environment variables.
            // Set OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET before running.
            var accessKeyId = Environment.GetEnvironmentVariable("OSS_ACCESS_KEY_ID");
            var accessKeySecret = Environment.GetEnvironmentVariable("OSS_ACCESS_KEY_SECRET");
            var bucketName = "examplebucket";
            var objectName = "exampledir/exampleobject.txt";
            var localFilename = "D:\\localpath\\examplefile.txt";
            const string region = "cn-hangzhou";

            var conf = new ClientConfiguration();
            conf.SignatureVersion = SignatureVersion.V4;

            var client = new OssClient(endpoint, accessKeyId, accessKeySecret, conf);
            client.SetRegion(region);

            try
            {
                using (var fs = File.Open(localFilename, FileMode.Open))
                {
                    var putObjectRequest = new PutObjectRequest(bucketName, objectName, fs);
                    putObjectRequest.StreamTransferProgress += streamProgressCallback;
                    client.PutObject(putObjectRequest);
                }
                Console.WriteLine("Put object:{0} succeeded", objectName);
            }
            catch (OssException ex)
            {
                Console.WriteLine("Failed with error code: {0}; Error info: {1}. \nRequestID: {2}\tHostID: {3}",
                    ex.ErrorCode, ex.Message, ex.RequestId, ex.HostId);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Failed with error info: {0}", ex.Message);
            }
        }

        private static void streamProgressCallback(object sender, StreamTransferProgressArgs args)
        {
            // args.TransferredBytes: total bytes uploaded so far.
            // args.TotalBytes: total object size.
            System.Console.WriteLine("ProgressCallback - Progress: {0}%, TotalBytes:{1}, TransferredBytes:{2} ",
                args.TransferredBytes * 100 / args.TotalBytes, args.TotalBytes, args.TransferredBytes);
        }
    }
}

Android

Set a progress callback on PutObjectRequest using setProgressCallback(). The SDK calls it asynchronously with currentSize (bytes uploaded so far) and totalSize (total object size in bytes).

// Specify the bucket name, object path, and local file path.
// Do not include the bucket name in the object path.
PutObjectRequest put = new PutObjectRequest("examplebucket", "exampledir/exampleobject.txt", "/storage/emulated/0/oss/examplefile.txt");

put.setProgressCallback(new OSSProgressCallback<PutObjectRequest>() {
    @Override
    public void onProgress(PutObjectRequest request, long currentSize, long totalSize) {
        // currentSize: bytes uploaded so far.
        // totalSize: total object size in bytes.
        Log.d("PutObject", "currentSize: " + currentSize + " totalSize: " + totalSize);
    }
});

// Upload the object asynchronously.
OSSAsyncTask task = oss.asyncPutObject(put, new OSSCompletedCallback<PutObjectRequest, PutObjectResult>() {
    @Override
    public void onSuccess(PutObjectRequest request, PutObjectResult result) {
        Log.d("PutObject", "UploadSuccess");
        Log.d("ETag", result.getETag());
        Log.d("RequestId", result.getRequestId());
    }

    @Override
    public void onFailure(PutObjectRequest request, ClientException clientExcepion, ServiceException serviceException) {
        if (clientExcepion != null) {
            // Handle client exceptions such as network errors.
            clientExcepion.printStackTrace();
        }
        if (serviceException != null) {
            // Handle service exceptions.
            Log.e("ErrorCode", serviceException.getErrorCode());
            Log.e("RequestId", serviceException.getRequestId());
            Log.e("HostId", serviceException.getHostId());
            Log.e("RawMessage", serviceException.getRawMessage());
        }
    }
});
// task.cancel(); // Cancel the upload task.
// task.waitUntilFinished(); // Block until the task completes.

PHP

Set progressFn on the PutObjectRequest object. The SDK calls it with increment (bytes in this interval), transferred (total bytes sent so far), and total (total object size).

<?php

require_once __DIR__ . '/../vendor/autoload.php';

use AlibabaCloud\Oss\V2 as Oss;

$optsdesc = [
    "region" => ['help' => 'The region where the bucket is located.', 'required' => True],
    "endpoint" => ['help' => 'The endpoint for OSS access.', 'required' => False],
    "bucket" => ['help' => 'The name of the bucket.', 'required' => True],
    "key" => ['help' => 'The name of the object.', 'required' => True],
];

$longopts = \array_map(function ($key) {
    return "$key:";
}, array_keys($optsdesc));

$options = getopt("", $longopts);

foreach ($optsdesc as $key => $value) {
    if ($value['required'] === True && empty($options[$key])) {
        $help = $value['help'];
        echo "Error: the following arguments are required: --$key, $help";
        exit(1);
    }
}

$region = $options["region"];
$bucket = $options["bucket"];
$key = $options["key"];

// Read credentials from environment variables.
// Set ALIBABA_CLOUD_ACCESS_KEY_ID and ALIBABA_CLOUD_ACCESS_KEY_SECRET before running.
$credentialsProvider = new Oss\Credentials\EnvironmentVariableCredentialsProvider();

$cfg = Oss\Config::loadDefault();
$cfg->setCredentialsProvider($credentialsProvider);
$cfg->setRegion($region);

if (isset($options["endpoint"])) {
    $cfg->setEndpoint($options["endpoint"]);
}

$client = new Oss\Client($cfg);

$data = 'Hello OSS';

$request = new Oss\Models\PutObjectRequest($bucket, $key);
$request->body = Oss\Utils::streamFor($data);

// increment: bytes uploaded in this interval.
// transferred: total bytes uploaded so far.
// total: total object size.
$request->progressFn = function (int $increment, int $transferred, int $total) {
    echo sprintf("Uploaded:%d" . PHP_EOL, $transferred);
    echo sprintf("This upload:%d" . PHP_EOL, $increment);
    echo sprintf("Total data:%d" . PHP_EOL, $total);
    echo '-------------------------------------------'. PHP_EOL;
};

$result = $client->putObject($request);

printf('status code: %s' . PHP_EOL, $result->statusCode);
printf('request id: %s' . PHP_EOL, $result->requestId);
printf('etag: %s' . PHP_EOL, $result->etag);

Go

Set ProgressFn in the PutObjectRequest struct. The SDK calls it with increment, transferred, and total (all int64) as the upload proceeds.

package main

import (
	"context"
	"flag"
	"fmt"
	"log"

	"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss"
	"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss/credentials"
)

var (
	region     string
	bucketName string
	objectName string
)

func init() {
	flag.StringVar(&region, "region", "", "The region where the bucket is located.")
	flag.StringVar(&bucketName, "bucket", "", "The name of the bucket.")
	flag.StringVar(&objectName, "object", "", "The name of the object.")
}

func main() {
	flag.Parse()

	if len(bucketName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, bucket name required")
	}
	if len(region) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, region required")
	}
	if len(objectName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, object name required")
	}

	// Read credentials from environment variables.
	// Set OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET before running.
	cfg := oss.LoadDefaultConfig().
		WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()).
		WithRegion(region)

	client := oss.NewClient(cfg)

	localFile := "/Users/localpath/exampleobject.txt"

	putRequest := &oss.PutObjectRequest{
		Bucket: oss.Ptr(bucketName),
		Key:    oss.Ptr(objectName),
		ProgressFn: func(increment, transferred, total int64) {
			// increment: bytes uploaded in this interval.
			// transferred: total bytes uploaded so far.
			// total: total object size.
			fmt.Printf("increment:%v, transferred:%v, total:%v\n", increment, transferred, total)
		},
	}

	result, err := client.PutObjectFromFile(context.TODO(), putRequest, localFile)
	if err != nil {
		log.Fatalf("failed to put object from file %v", err)
	}

	log.Printf("put object from file result:%#v\n", result)
}

iOS

Set the uploadProgress block on OSSPutObjectRequest. The block receives bytesSent (bytes in this interval), totalByteSent (total bytes sent so far), and totalBytesExpectedToSend (total object size).

OSSPutObjectRequest *put = [OSSPutObjectRequest new];
// Specify the bucket name.
put.bucketName = @"examplebucket";
// Specify the object path. Do not include the bucket name in the path.
put.objectKey = @"exampledir/exampleobject.txt";
// Specify the full path of the local file to upload.
put.uploadingFileURL = [NSURL fileURLWithPath:@"filePath"];

// bytesSent: bytes uploaded in this interval.
// totalByteSent: total bytes uploaded so far.
// totalBytesExpectedToSend: total object size.
put.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) {
    NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);
};

OSSTask *putTask = [client putObject:put];
[putTask continueWithBlock:^id(OSSTask *task) {
    if (!task.error) {
        NSLog(@"upload object success!");
    } else {
        NSLog(@"upload object failed, error: %@", task.error);
    }
    return nil;
}];
// [putTask waitUntilFinished]; // Uncomment to block until the upload completes.

C++

Define a ProgressCallback function and attach it to PutObjectRequest via a TransferProgress struct using setTransferProgress(). The callback receives increment (bytes in this interval), transferred (total bytes sent so far), and total (total object size).

#include <alibabacloud/oss/OssClient.h>
#include <fstream>
using namespace AlibabaCloud::OSS;

void ProgressCallback(size_t increment, int64_t transferred, int64_t total, void* userData)
{
    // increment: bytes uploaded in this interval.
    // transferred: total bytes uploaded so far.
    // total: total object size.
    std::cout << "ProgressCallback[" << userData << "] => " <<
    increment << " ," << transferred << "," << total << std::endl;
}

int main(void)
{
    // Specify the endpoint of the region where your bucket is located.
    // Example: https://oss-cn-hangzhou.aliyuncs.com
    std::string Endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
    std::string Region = "cn-hangzhou";
    std::string BucketName = "examplebucket";
    std::string ObjectName = "exampledir/exampleobject.txt";

    InitializeSdk();

    ClientConfiguration conf;
    conf.signatureVersion = SignatureVersionType::V4;
    // Read credentials from environment variables.
    // Set OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET before running.
    auto credentialsProvider = std::make_shared<EnvironmentVariableCredentialsProvider>();
    OssClient client(Endpoint, credentialsProvider, conf);
    client.SetRegion(Region);

    // Specify the full path of the local file to upload.
    std::shared_ptr<std::iostream> content = std::make_shared<std::fstream>("D:\\localpath\\examplefile.txt", std::ios::in|std::ios::binary);
    PutObjectRequest request(BucketName, ObjectName, content);

    TransferProgress progressCallback = { ProgressCallback, nullptr };
    request.setTransferProgress(progressCallback);

    auto outcome = client.PutObject(request);

    if (!outcome.isSuccess()) {
        std::cout << "PutObject fail" <<
        ",code:" << outcome.error().Code() <<
        ",message:" << outcome.error().Message() <<
        ",requestId:" << outcome.error().RequestId() << std::endl;
        ShutdownSdk();
        return -1;
    }

    ShutdownSdk();
    return 0;
}

C

Pass a percentage callback function to oss_do_put_object_from_file(). The callback receives consumed_bytes (total bytes uploaded so far) and total_bytes (total object size).

#include "oss_api.h"
#include "aos_http_io.h"

/* Specify the endpoint of the region where your bucket is located.
   Example: https://oss-cn-hangzhou.aliyuncs.com */
const char *endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
const char *bucket_name = "examplebucket";
const char *object_name = "exampledir/exampleobject.txt";
const char *local_filename = "D:\\localpath\\examplefile.txt";
const char *region = "cn-hangzhou";

void init_options(oss_request_options_t *options)
{
    options->config = oss_config_create(options->pool);
    aos_str_set(&options->config->endpoint, endpoint);
    /* Read credentials from environment variables.
       Set OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET before running. */
    aos_str_set(&options->config->access_key_id, getenv("OSS_ACCESS_KEY_ID"));
    aos_str_set(&options->config->access_key_secret, getenv("OSS_ACCESS_KEY_SECRET"));
    aos_str_set(&options->config->region, region);
    options->config->signature_version = 4;
    /* Set to 0 to disable CNAME. */
    options->config->is_cname = 0;
    options->ctl = aos_http_controller_create(options->pool, 0);
}

/* consumed_bytes: total bytes uploaded so far.
   total_bytes: total object size. */
void percentage(int64_t consumed_bytes, int64_t total_bytes)
{
    assert(total_bytes >= consumed_bytes);
    printf("%%%" APR_INT64_T_FMT "\n", consumed_bytes * 100 / total_bytes);
}

int main(int argc, char *argv[])
{
    if (aos_http_io_initialize(NULL, 0) != AOSE_OK) {
        exit(1);
    }

    aos_pool_t *pool;
    aos_pool_create(&pool, NULL);

    oss_request_options_t *oss_client_options;
    oss_client_options = oss_request_options_create(pool);
    init_options(oss_client_options);

    aos_string_t bucket;
    aos_string_t object;
    aos_string_t file;
    aos_list_t resp_body;
    aos_table_t *resp_headers = NULL;
    aos_status_t *resp_status = NULL;

    aos_str_set(&bucket, bucket_name);
    aos_str_set(&object, object_name);
    aos_str_set(&file, local_filename);

    resp_status = oss_do_put_object_from_file(oss_client_options, &bucket, &object, &file, NULL, NULL, percentage, &resp_headers, &resp_body);
    if (aos_status_is_ok(resp_status)) {
        printf("put object from file succeeded\n");
    } else {
        printf("put object from file failed\n");
    }

    aos_pool_destroy(pool);
    aos_http_io_deinitialize();
    return 0;
}

What's next

  • To track upload progress for multipart uploads or other upload operations, see Overview.