All Products
Search
Document Center

Object Storage Service:Append upload

Last Updated:Dec 05, 2025

Append upload lets you append content directly to the end of an existing appendable object.

Prerequisites

A bucket is created. For more information, see Create buckets.

Background information

Objects created using simple upload are Normal objects, and objects created using multipart upload are Multipart objects. After an upload is complete, the content of these two object types is fixed. You can only read them. You cannot modify them. If the object content changes, you must upload an object with the same name again to overwrite the existing content.

Because of this limitation, if you use these methods to upload real-time video streams from sources such as video surveillance systems or ApsaraVideo Live, you can only chunk the video stream into smaller pieces and continuously upload them as new objects. This approach has the following disadvantages:

  • The software architecture is complex. You must manage details such as file chunking.

  • You need a location to store metadata, such as a list of generated objects. Then, each request must repeatedly read the metadata to check whether new objects are generated. This places a heavy load on the server. The client also needs to send two network requests each time, which can increase latency.

  • If you chunk objects into smaller pieces, you can reduce data latency. However, many small objects makes management complex. If you chunk objects into larger pieces, data latency increases significantly.

To update the content of an uploaded video stream in real-time, you can first splice the video locally. Then, you can upload the video using the append upload (AppendObject) feature provided by Object Storage Service (OSS). This creates an appendable object. You can directly append content to an appendable object. The appended data is readable immediately after each append operation.

Benefits

With append upload, you can upload video data to the same object as soon as the data is generated. The client only needs to periodically retrieve the object's length and compare it with the previously read length. If new readable data is found, the client triggers a read operation to retrieve the newly uploaded data. This method simplifies the architecture and improves extensibility.

Limits

  • Size limit

    The object size cannot exceed 5 GB.

  • Operation limits

    • You cannot use append upload to upload Cold Archive or Deep Cold Archive objects.

    • Append upload does not support upload callbacks.

Notes

  • If the object does not exist, calling the AppendObject API operation creates an appendable object.

  • If the object already exists:

    • If the object is an appendable object and the specified append position equals the current object length, the content is appended to the end of the object.

    • If the object is an appendable object but the specified append position does not equal the current object length, a PositionNotEqualToLength exception is thrown.

    • If the object is a non-appendable object, such as a Normal object uploaded using simple upload, an ObjectNotAppendable exception is thrown.

Methods

Use an Alibaba Cloud SDK

The following sections provide code examples for append uploads using common software development kits (SDKs). For code examples that use other SDKs, see SDK overview.

import com.aliyun.oss.*;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.common.comm.SignVersion;
import com.aliyun.oss.model.AppendObjectRequest;
import com.aliyun.oss.model.AppendObjectResult;
import com.aliyun.oss.model.ObjectMetadata;
import java.io.ByteArrayInputStream;

public class Demo {

    public static void main(String[] args) throws Exception {
        // The endpoint of the China (Hangzhou) region is used as an example. Specify the actual endpoint.
        String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
        // Obtain access credentials from environment variables. Before running the sample code, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are set.
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
        // Specify the bucket name, for example, examplebucket.
        String bucketName = "examplebucket";
        // Specify the full path of the object. The full path cannot contain the bucket name. Example: exampledir/exampleobject.txt.
        String objectName = "exampledir/exampleobject.txt";
        String content1 = "Hello OSS A \n";
        String content2 = "Hello OSS B \n";
        String content3 = "Hello OSS C \n";
        // Specify the region where the bucket is located. For example, if the bucket is in the China (Hangzhou) region, set Region to cn-hangzhou.
        String region = "cn-hangzhou";

        // Create an OSSClient instance.
        // When the OSSClient instance is no longer in use, call the shutdown method to release resources.
        ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
        clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);        
        OSS ossClient = OSSClientBuilder.create()
        .endpoint(endpoint)
        .credentialsProvider(credentialsProvider)
        .clientConfiguration(clientBuilderConfiguration)
        .region(region)               
        .build();

        try {
            ObjectMetadata meta = new ObjectMetadata();
            // Specify the content type of the upload.
            meta.setContentType("text/plain");
            // Specify the web page caching behavior for the object.
            //meta.setCacheControl("no-cache");
            // Specify the name of the object when it is downloaded.
            //meta.setContentDisposition("attachment;filename=oss_download.txt");
            // Specify the content encoding format of the object.
            //meta.setContentEncoding(OSSConstants.DEFAULT_CHARSET_NAME);
            // This request header is used to check whether the message content is consistent with the content sent.
            //meta.setContentMD5("ohhnqLBJFiKkPSBO1eNaUA==");
            // Specify the expiration time.
            //try {
            //    meta.setExpirationTime(DateUtil.parseRfc822Date("Wed, 08 Jul 2022 16:57:01 GMT"));
            //} catch (ParseException e) {
            //    e.printStackTrace();
            //}
            // Specify the server-side encryption method. In this example, server-side encryption with OSS-managed keys (SSE-OSS) is used.
            //meta.setServerSideEncryption(ObjectMetadata.AES_256_SERVER_SIDE_ENCRYPTION);
            // Specify the access permissions of the object. In this example, the private access permission is specified.
            //meta.setObjectAcl(CannedAccessControlList.Private);
            // Specify the storage class of the object.
            //meta.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard);
            // You can add x-oss-meta-* when you create an AppendObject. You cannot carry this parameter for subsequent appends. If you configure a parameter prefixed with x-oss-meta-*, the parameter is considered metadata.
            //meta.setHeader("x-oss-meta-author", "Alice");

            // Set multiple parameters through AppendObjectRequest.
            AppendObjectRequest appendObjectRequest = new AppendObjectRequest(bucketName, objectName, new ByteArrayInputStream(content1.getBytes()),meta);

            // Set a single parameter through AppendObjectRequest.
            // Set the bucket name.
            //appendObjectRequest.setBucketName(bucketName);
            // Set the object name.
            //appendObjectRequest.setKey(objectName);
            // Set the content to be appended. The type can be InputStream or File. In this example, the type is InputStream.
            //appendObjectRequest.setInputStream(new ByteArrayInputStream(content1.getBytes()));
            // Set the content to be appended. The type can be InputStream or File. In this example, the type is File.
            //appendObjectRequest.setFile(new File("D:\\localpath\\examplefile.txt"));
            // Specify the metadata of the file. This is valid only for the first append.
            //appendObjectRequest.setMetadata(meta);

            // First append.
            // Set the append position of the file.
            appendObjectRequest.setPosition(0L);
            AppendObjectResult appendObjectResult = ossClient.appendObject(appendObjectRequest);
            // The 64-bit CRC value of the file.
            System.out.println(appendObjectResult.getObjectCRC());

            // Second append.
            // nextPosition indicates the position that should be provided in the next request, which is the current length of the file.
            appendObjectRequest.setPosition(appendObjectResult.getNextPosition());
            appendObjectRequest.setInputStream(new ByteArrayInputStream(content2.getBytes()));
            appendObjectResult = ossClient.appendObject(appendObjectRequest);

            // Third append.
            appendObjectRequest.setPosition(appendObjectResult.getNextPosition());
            appendObjectRequest.setInputStream(new ByteArrayInputStream(content3.getBytes()));
            appendObjectResult = ossClient.appendObject(appendObjectRequest);
        } 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();
            }
        }
    }
}
const OSS = require('ali-oss')

const client = new OSS({
  // Specify the region in which the bucket is located. For example, if your bucket is located in the China (Hangzhou) region, set the region to oss-cn-hangzhou. 
  region: 'yourRegion',
  // Obtain access credentials from environment variables. Before you run the sample code, make sure that you have configured environment variables OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET. 
  accessKeyId: process.env.OSS_ACCESS_KEY_ID,
  accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET,
  authorizationV4: true,
  // Specify the name of the bucket. Example: examplebucket. 
  bucket: 'examplebucket',
});

const headers = {    
  // Specify the access control list (ACL) of the object. 
  'x-oss-object-acl': 'private',
  // Specify the storage class of the object. 
  'x-oss-storage-class': 'Standard',  
  // Specify the server-side encryption method. In this example, SSE-OSS is used. 
  'x-oss-server-side-encryption': 'AES256',  
};

async function append () {
  // Perform the first append upload operation. The position from which the next append operation starts is included in the response. 
  // Specify the full path of the object. Do not include the bucket name in the full path. Example: destfolder/examplefile.txt. 
  // Specify the full path of the local file. The full path contains the suffix. Example: /users/local/examplefile.txt. 
  const result = await client.append('objectName', 'localFile'
  // Specify custom headers and user metadata. 
  //,{headers} 
  )

  // Perform the second append operation. The position from which the next append operation starts is the current length of the object, which is specified by Content-Length. 
  result = await client.append('objectName', 'localFile', {
    position: result.nextAppendPosition
  })
}

append();
using Aliyun.OSS;
using Aliyun.OSS.Common;

// Specify the endpoint of the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the endpoint to https://oss-cn-hangzhou.aliyuncs.com. 
var endpoint = "yourEndpoint";
// Obtain access credentials from environment variables. Before you run the sample code, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are configured. 
var accessKeyId = Environment.GetEnvironmentVariable("OSS_ACCESS_KEY_ID");
var accessKeySecret = Environment.GetEnvironmentVariable("OSS_ACCESS_KEY_SECRET");
// Specify the name of the bucket. Example: examplebucket. 
var bucketName = "examplebucket";
// Specify the full path of the object. Do not include the bucket name in the full path. Example: exampledir/exampleobject.txt. 
var objectName = "exampledir/exampleobject.txt";
// Specify the full path of the local file. Example: D:\\localpath\\examplefile.txt. By default, if you do not specify the path of the local file, the file is uploaded from the path of the project to which the sample program belongs. 
var localFilename = "D:\\localpath\\examplefile.txt";
// Specify the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the region to cn-hangzhou.
const string region = "cn-hangzhou";

// Create a ClientConfiguration instance and modify the default parameters based on your requirements.
var conf = new ClientConfiguration();

// Use the signature algorithm V4.
conf.SignatureVersion = SignatureVersion.V4;

// Create an OSSClient instance.
var client = new OssClient(endpoint, accessKeyId, accessKeySecret, conf);
c.SetRegion(region);
// The position for the first append upload is 0, and the position for the next append upload is included in the response. The position from which the next append operation starts is the current length of the object. 
long position = 0;
try
{
    var metadata = client.GetObjectMetadata(bucketName, objectName);
    position = metadata.ContentLength;
}
catch (Exception) { }
try
{
    using (var fs = File.Open(localFilename, FileMode.Open))
    {
        var request = new AppendObjectRequest(bucketName, objectName)
        {
            ObjectMetadata = new ObjectMetadata(),
            Content = fs,
            Position = position
        };
        // Perform the append operation. 
        var result = client.AppendObject(request);
        // Specify the position from which the append operation starts. 
        position = result.NextAppendPosition;
        Console.WriteLine("Append object succeeded, next append position:{0}", position);
    }
    // Query the position from which the next append operation starts and perform the second append operation. 
    using (var fs = File.Open(localFilename, FileMode.Open))
    {
        var request = new AppendObjectRequest(bucketName, objectName)
        {
            ObjectMetadata = new ObjectMetadata(),
            Content = fs,
            Position = position
        };
        var result = client.AppendObject(request);
        position = result.NextAppendPosition;
        Console.WriteLine("Append object succeeded, next append position:{0}", position);
    }
}
catch (Exception ex)
{
    Console.WriteLine("Append object failed, {0}", ex.Message);
}
b/ Specify the name of the bucket, the full path of the object, and the full path of the local file. In this example, the name of the bucket is examplebucket, the full path of the object is exampledir/exampleobject.txt, and the full path of the local file is /storage/emulated/0/oss/examplefile.txt. 
// Do not include the bucket name in the full path of the object. 
AppendObjectRequest append = new AppendObjectRequest("examplebucket", "exampledir/exampleobject.txt", "/storage/emulated/0/oss/examplefile.txt");

ObjectMetadata metadata = new ObjectMetadata();
metadata.setContentType("text/plain");
append.setMetadata(metadata);

// Specify the position from which the append operation starts. 
append.setPosition(0);

// Configure callbacks. 
append.setProgressCallback(new OSSProgressCallback<AppendObjectRequest>() {
    @Override
    public void onProgress(AppendObjectRequest request, long currentSize, long totalSize) {
        Log.d("AppendObject", "currentSize: " + currentSize + " totalSize: " + totalSize);
    }
});
// Perform the append upload operation in the asynchronous mode. 
OSSAsyncTask task = oss.asyncAppendObject(append, new OSSCompletedCallback<AppendObjectRequest, AppendObjectResult>() {
    @Override
    public void onSuccess(AppendObjectRequest request, AppendObjectResult result) {
        Log.d("AppendObject", "AppendSuccess");
        Log.d("NextPosition", "" + result.getNextPosition());
    }

    @Override
    public void onFailure(AppendObjectRequest request, ClientException clientExcepion, ServiceException serviceException) {
        // Handle exceptions. 
    }
});
OSSAppendObjectRequest * append = [OSSAppendObjectRequest new];
// Configure the required fields. bucketName indicates the name of the bucket. objectKey is equivalent to objectName that indicates the full path of the object you want to upload to OSS by using append upload. The path must include the extension of the object. For example, you can set objectKey to abc/efg/123.jpg. 
append.bucketName = @"<bucketName>";
append.objectKey = @"<objectKey>";
// Specify the position from which the first append operation starts. 
append.appendPosition = 0; 
NSString * docDir = [self getDocumentDirectory];
append.uploadingFileURL = [NSURL fileURLWithPath:@"<filepath>"];
// Configure the optional fields. 
append.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) {
    NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);
};
// append.contentType = @"";
// append.contentMd5 = @"";
// append.contentEncoding = @"";
// append.contentDisposition = @"";
OSSTask * appendTask = [client appendObject:append];
[appendTask continueWithBlock:^id(OSSTask *task) {
    NSLog(@"objectKey: %@", append.objectKey);
    if (!task.error) {
        NSLog(@"append object success!");
        OSSAppendObjectResult * result = task.result;
        NSString * etag = result.eTag;
        long nextPosition = result.xOssNextAppendPosition;
    } else {
        NSLog(@"append object failed, error: %@" , task.error);
    }
    return nil;
}];
#include <alibabacloud/oss/OssClient.h>
using namespace AlibabaCloud::OSS;

int main(void)
{
    /* Initialize information about the account that is used to access OSS. */
            
    /* Specify the endpoint of the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the endpoint to https://oss-cn-hangzhou.aliyuncs.com. */
    std::string Endpoint = "yourEndpoint";
    /* Specify the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the region to cn-hangzhou. */
    std::string Region = "yourRegion";
    /* Specify the name of the bucket. Example: examplebucket. */
    std::string BucketName = "examplebucket";
    /* Specify the full path of the object. Do not include the bucket name in the full path of the object. Example: exampledir/exampleobject.txt. */
    std::string ObjectName = "exampledir/exampleobject.txt";

    /* Initialize resources such as network resources. */
    InitializeSdk();

    ClientConfiguration conf;
    conf.signatureVersion = SignatureVersionType::V4;
    /* Obtain access credentials from environment variables. Before you run the sample code, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are configured. */
    auto credentialsProvider = std::make_shared<EnvironmentVariableCredentialsProvider>();
    OssClient client(Endpoint, credentialsProvider, conf);
    client.SetRegion(Region);

    auto meta = ObjectMetaData();
    meta.setContentType("text/plain");

    /* If the object is appended for the first time, set the position from which the append operation starts to 0. The position for the next append operation is included in the response. The position from which the next append upload starts is the current length of the object. */
    std::shared_ptr<std::iostream> content1 = std::make_shared<std::stringstream>();
    *content1 <<"Thank you for using Aliyun Object Storage Service!";
    AppendObjectRequest request(BucketName, ObjectName, content1, meta);
    request.setPosition(0L);

    /* Perform the first append operation. */
    auto result = client.AppendObject(request);

    if (!result.isSuccess()) {
        /* Handle exceptions. */
        std::cout << "AppendObject fail" <<
        ",code:" << result.error().Code() <<
        ",message:" << result.error().Message() <<
        ",requestId:" << result.error().RequestId() << std::endl;
        return -1;
    }

    std::shared_ptr<std::iostream> content2 = std::make_shared<std::stringstream>();
    *content2 <<"Thank you for using Aliyun Object Storage Service!";
    auto position = result.result().Length();
    AppendObjectRequest appendObjectRequest(BucketName, ObjectName, content2);
    appendObjectRequest.setPosition(position);

    /* Perform the second append operation. */
    auto outcome = client.AppendObject(appendObjectRequest);

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

    /* Release resources such as network resources. */
    ShutdownSdk();
    return 0;
}
#include "oss_api.h"
#include "aos_http_io.h"
/* Specify the endpoint of the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the endpoint to https://oss-cn-hangzhou.aliyuncs.com. */
const char *endpoint = "yourEndpoint";

/* Specify the name of the bucket. Example: examplebucket. */
const char *bucket_name = "examplebucket";
/* Specify the full path of the object. Do not include the bucket name in the full path of the object. Example: exampledir/exampleobject.txt. */
const char *object_name = "exampledir/exampleobject.txt";
const char *object_content = "More than just cloud.";
/* Specify the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the region to cn-hangzhou. */
const char *region = "yourRegion";
void init_options(oss_request_options_t *options)
{
    options->config = oss_config_create(options->pool);
    /* Use a char* string to initialize data of the aos_string_t type. */
    aos_str_set(&options->config->endpoint, endpoint);
    /* Obtain access credentials from environment variables. Before you run the sample code, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are configured. */    
    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"));
    // Specify two additional parameters.
    aos_str_set(&options->config->region, region);
    options->config->signature_version = 4;
    /* Specify whether to use CNAME. The value 0 indicates that CNAME is not used. */
    options->config->is_cname = 0;
    /* Specify network parameters, such as the timeout period. */
    options->ctl = aos_http_controller_create(options->pool, 0);
}
int main(int argc, char *argv[])
{
    /* Call the aos_http_io_initialize method in main() to initialize global resources, such as network resources and memory resources. */
    if (aos_http_io_initialize(NULL, 0) != AOSE_OK) {
        exit(1);
    }
    /* Create a memory pool to manage memory. aos_pool_t is equivalent to apr_pool_t. The code used to create a memory pool is included in the APR library. */
    aos_pool_t *pool;
    /* Create a memory pool. The value of the second parameter is NULL. This value indicates that the pool does not inherit other memory pools. */
    aos_pool_create(&pool, NULL);
    /* Create and initialize options. This parameter includes global configuration information, such as endpoint, access_key_id, access_key_secret, is_cname, and curl. */
    oss_request_options_t *oss_client_options;
    /* Allocate the memory resources in the memory pool to the options. */
    oss_client_options = oss_request_options_create(pool);
    /* Initialize oss_client_options. */
    init_options(oss_client_options);
    /* Initialize the parameters. */
    aos_string_t bucket;
    aos_string_t object;
    aos_list_t buffer;
    int64_t position = 0;
    char *next_append_position = NULL;
    aos_buf_t *content = NULL;
    aos_table_t *headers1 = NULL;
    aos_table_t *headers2 = NULL;
    aos_table_t *resp_headers = NULL; 
    aos_status_t *resp_status = NULL; 
    aos_str_set(&bucket, bucket_name);
    aos_str_set(&object, object_name);
    headers1 = aos_table_make(pool, 0);
    /* Obtain the position from which the first append operation starts. */
    resp_status = oss_head_object(oss_client_options, &bucket, &object, headers1, &resp_headers);
    if (aos_status_is_ok(resp_status)) {
        next_append_position = (char*)(apr_table_get(resp_headers, "x-oss-next-append-position"));
        position = atoi(next_append_position);
    }
    /* Perform the append operation. */
    headers2 = aos_table_make(pool, 0);
    aos_list_init(&buffer);
    content = aos_buf_pack(pool, object_content, strlen(object_content));
    aos_list_add_tail(&content->node, &buffer);
    resp_status = oss_append_object_from_buffer(oss_client_options, &bucket, &object, position, &buffer, headers2, &resp_headers);
    if (aos_status_is_ok(resp_status)) {
        printf("append object from buffer succeeded\n");
    } else {
        printf("append object from buffer failed\n");
    }
    /* Release the memory pool. This operation releases the memory resources allocated for the request. */
    aos_pool_destroy(pool);
    /* Release the allocated global resources. */
    aos_http_io_deinitialize();
    return 0;
}
require 'aliyun/oss'

client = Aliyun::OSS::Client.new(
  # In this example, the endpoint of the China (Hangzhou) region is used. Specify your actual endpoint. 
  endpoint: 'https://oss-cn-hangzhou.aliyuncs.com',
  # Obtain access credentials from environment variables. Before you run the sample code, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are configured. 
  access_key_id: ENV['OSS_ACCESS_KEY_ID'],
  access_key_secret: ENV['OSS_ACCESS_KEY_SECRET']
)

# Specify the name of the bucket. Example: examplebucket. 
bucket = client.get_bucket('examplebucket')
# Replace my-object with the full path of the object. Do not include the bucket name in the full path. 
bucket.append_object('my-object', 0)

# Append content to the end of the object. 
next_pos = bucket.append_object('my-object', 0) do |stream|
  100.times { |i| stream << i.to_s }
end
next_pos = bucket.append_object('my-object', next_pos, :file => 'local-file-1')
next_pos = bucket.append_object('my-object', next_pos, :file => 'local-file-2')
package main

import (
	"context"
	"flag"
	"log"
	"strings"

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

// Specify the global variables.
var (
	region     string
	bucketName string
	objectName string
)

// Specify the init function used to initialize command line parameters.
func init() {
	flag.StringVar(&region, "region", "", "The region in which the bucket is located.")
	flag.StringVar(&bucketName, "bucket", "", "The name of the bucket.")
	flag.StringVar(&objectName, "object", "", "The name of the object.")
}

func main() {
	// Parse command line parameters.
	flag.Parse()

	// Specify the position from which the append operation starts.
	var (
		position = int64(0)
	)

	// Check whether the bucket name is empty.
	if len(bucketName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, bucket name required")
	}

	// Check whether the region is empty.
	if len(region) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, region required")
	}

	// Check whether the object name is empty.
	if len(objectName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, object name required")
	}

	// Load the default configurations and specify the credential provider and region.
	cfg := oss.LoadDefaultConfig().
		WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()).
		WithRegion(region)

	// Create an OSSClient instance.
	client := oss.NewClient(cfg)

	// Specify the content that you want to append.
	content := "hi append object"

	// Create an AppendObject request to perform the first append operation.
	request := &oss.AppendObjectRequest{
		Bucket:   oss.Ptr(bucketName),
		Key:      oss.Ptr(objectName),
		Position: oss.Ptr(position),
		Body:     strings.NewReader(content),
	}

	// Execute the AppendObject request and process the result.
	// The first time an object is appended, the append operation starts at 0. The position for the next append operation is included in the response.
	result, err := client.AppendObject(context.TODO(), request)
	if err != nil {
		log.Fatalf("failed to append object %v", err)
	}

	// Create an AppendObject request to perform the second append operation.
	request = &oss.AppendObjectRequest{
		Bucket:   oss.Ptr(bucketName),
		Key:      oss.Ptr(objectName),
		Position: oss.Ptr(result.NextPosition), // Obtain the value of the NextPosition parameter from the response to the first AppendObject request.
		Body:     strings.NewReader("hi append object"),
	}

	// Execute the AppendObject request and process the result.
	result, err = client.AppendObject(context.TODO(), request)
	if err != nil {
		log.Fatalf("failed to append object %v", err)
	}

	log.Printf("append object result:%#v\n", result)
}
import argparse
import alibabacloud_oss_v2 as oss

# Create a command-line argument parser.
parser = argparse.ArgumentParser(description="append object sample")

# Add command line parameters
# --region: Specify the region where the OSS bucket is located
parser.add_argument('--region', help='The region in which the bucket is located.', required=True)
# --bucket: Specify the name of the bucket to operate on
parser.add_argument('--bucket', help='The name of the bucket.', required=True)
# --endpoint: Optional parameter, specify the domain name for accessing OSS service
parser.add_argument('--endpoint', help='The domain names that other services can use to access OSS')
# --key: Specify the key name of the object (file) in OSS
parser.add_argument('--key', help='The name of the object.', required=True)

def main():
    # Parse the command line parameters.
    args = parser.parse_args()

    # Obtain access credentials from environment variables for authentication.
    credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider()

    # Use the default configurations of the SDK to create a configuration object.
    cfg = oss.config.load_default()

    # Set the credential provider to the previously created object
    cfg.credentials_provider = credentials_provider

    # Set the region for the OSS client based on user input
    cfg.region = args.region

    # If the user provided a custom endpoint, update the configuration
    if args.endpoint is not None:
        cfg.endpoint = args.endpoint

    # Use the preceding configuration to initialize the OSSClient instance.
    client = oss.Client(cfg)

    # Define the data to append
    data1 = b'hello'
    data2 = b' world'

    # First append operation
    result = client.append_object(oss.AppendObjectRequest(
        bucket=args.bucket,  # Specify the bucket name.
        key=args.key,  # Specify the object key name
        position=0,  # The starting position for append, initially 0
        body=data1,  # The data to append
    ))

    # Print the result of the first append
    print(f'status code: {result.status_code},'
          f' request id: {result.request_id},'
          f' version id: {result.version_id},'
          f' hash crc64: {result.hash_crc64},'
          f' next position: {result.next_position},' 
    )

    # Second append operation
    result = client.append_object(oss.AppendObjectRequest(
        bucket=args.bucket,  # Specify the bucket name.
        key=args.key,  # Specify the object key name
        position=result.next_position,  # Start from the next position after the previous append
        body=data2,  # The data to append
    ))

    # Print the result of the second append
    print(f'status code: {result.status_code},'
          f' request id: {result.request_id},'
          f' version id: {result.version_id},'
          f' hash crc64: {result.hash_crc64},'
          f' next position: {result.next_position},'
    )

# Call the main function when the script is directly run.
if __name__ == "__main__":
    main()
<?php

// Introduce autoload files to load dependency libraries.
require_once __DIR__ . '/../vendor/autoload.php';

use AlibabaCloud\Oss\V2 as Oss;

// Define and describe command-line parameters.
$optsdesc = [
    "region" => ['help' => 'The region in which the bucket is located.', 'required' => True], // (Required) Specify the region in which the bucket is located.
    "endpoint" => ['help' => 'The domain names that other services can use to access OSS.', 'required' => False], // (Optional) Specify the endpoint for accessing OSS.
    "bucket" => ['help' => 'The name of the bucket', 'required' => True], // (Required) Specify the name of the bucket.
    "key" => ['help' => 'The name of the object', 'required' => True], // (Required) Specify the name of the object.
];

// Convert the descriptions to a list of long options required by getopt.
// Add a colon (:) to the end of each parameter to indicate that a value is required.
$longopts = \array_map(function ($key) {
    return "$key:";
}, array_keys($optsdesc));

// Parse the command-line parameters.
$options = getopt("", $longopts);

// Check whether the required parameters are configured.
foreach ($optsdesc as $key => $value) {
    if ($value['required'] === True && empty($options[$key])) {
        $help = $value['help']; // Obtain help information for the parameters.
        echo "Error: the following arguments are required: --$key, $help" . PHP_EOL;
        exit(1); // Exit the program if a required parameter is missing.
    }
}

// Assign the values parsed from the command-line parameters to the corresponding variables.
$region = $options["region"]; // The region in which the bucket is located.
$bucket = $options["bucket"]; // The name of the bucket.
$key = $options["key"];       // The name of the object.

// Load access credentials from environment variables.
// Use EnvironmentVariableCredentialsProvider to retrieve the AccessKey ID and AccessKey secret from environment variables.
$credentialsProvider = new Oss\Credentials\EnvironmentVariableCredentialsProvider();

// Use the default configuration of the SDK.
$cfg = Oss\Config::loadDefault();
$cfg->setCredentialsProvider($credentialsProvider); // Specify the credential provider.
$cfg->setRegion($region); // Specify the region in which the bucket is located.
if (isset($options["endpoint"])) {
    $cfg->setEndpoint($options["endpoint"]); // Specify the endpoint if one is provided.
}

// Create an OSSClient instance.
$client = new Oss\Client($cfg);

// Specify the content that you want to append.
$data='Hello Append Object'; // Replace the sample data with your actual content.

// Create an AppendObjectRequest object to append data to a specific object.
$request = new Oss\Models\AppendObjectRequest(bucket: $bucket, key: $key);
$request->body = Oss\Utils::streamFor($data); // Specify that the HTTP request body is a binary stream.
$request->position = 0; // Set the position from which the first append operation starts to 0.

// Perform the append upload operation.
$result = $client->appendObject($request);

// Display the result.
// Display the HTTP status code and the request ID to check whether the request succeeded.
printf(
    'status code:' . $result->statusCode . PHP_EOL . // The HTTP status code. For example, HTTP status code 200 indicates that the request succeeded.
    'request id:' . $result->requestId . PHP_EOL .    // The request ID, which is used to debug or trace a request.
    'next append position:' . $result->nextPosition . PHP_EOL // Specify the position from which the next append operation starts.
);

Use the ossutil command line interface

You can use the ossutil command line interface (CLI) to append and upload objects. To install ossutil, see Install ossutil.

The following command appends content to the `exampleobject` object as a string.

ossutil api append-object --bucket examplebucket --key exampleobject --position 0 --body "hi oss"

For more information about this command, see append-object.

Related API operations

The preceding methods are based on API operations. If your program has high customization requirements, you can directly send REST API requests. To directly send REST API requests, you must manually write code to calculate signatures. For more information, see AppendObject.

FAQ

Are there any file type restrictions for append upload?

No. Append upload recognizes only binary streams and has no requirements for file types.

How do I convert a non-appendable file to an appendable file?

OSS does not support directly converting a non-appendable object to an appendable object. However, you can use the following method to perform the conversion:

  1. Use the AppendObject API operation to create a new, empty appendable object.

  2. Download the original object and read its content.

  3. Use the AppendObject API operation to append the content to the newly created object.

Important

The conversion process involves re-reading and re-uploading the content. After the conversion is complete, verify the availability of the object.