You can perform append upload to append content to an appendable object.

Prerequisites

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

Background information

Objects that are uploaded by using simple upload are considered normal objects. Objects that are uploaded by using multipart upload are considered multipart objects. For more information, see Simple upload and Multipart upload. The content of normal and multipart objects can be only read and not modified after the objects are uploaded. To change the content of an existing normal or multipart object, you must upload an object with the same name as the existing object to overwrite the existing object.

If you use simple upload or multipart upload to upload real-time video streams generated by surveillance and live streaming services, you must split the streams into parts based on specific rules and continuously upload new parts to OSS as separated objects. This upload method has the following disadvantages:

  • You must develop a complex software to handle the details during upload, such as splitting the streams into parts.
  • You must reserve storage spaces to store object metadata, such as the list of uploaded objects. The client must repeatedly query the metadata to determine whether a new object is uploaded. In this case, the client must send two requests to check whether new objects are uploaded, which increases network latency and the workload on the OSS server.
  • If the streams are split into small objects, the network latency decreases, but object management becomes more complex. If the streams are split into large objects, the network latency significantly increases.

To update the content of uploaded objects in real time in the preceding scenarios, OSS allows you to use append upload to append data to existing appendable objects. Objects uploaded by using append upload are considered appendable objects. You can append content to existing appendable objects. Data that is appended to an appendable object can be immediately read.

Benefits

You can use append upload to upload the data generated by a video stream to a single object. The client only needs to periodically compare the current length of the object with the object length obtained last time to determine whether new data is uploaded. If the client determines that new data is appended, the client sends a request to obtain the appended data. This way, you can simplify the architecture and improve scalability.

Limits

  • Object size

    The object that you can upload by using append upload cannot be larger than 5 GB in size.

  • Object names
    • The name must be encoded in UTF-8.
    • The name must be 1 to 1,023 characters in length.
    • The name cannot start with a forward slash (/) or a backslash (\).
  • API operations
    • Appendable objects cannot be copied. However, you can modify the metadata of appendable objects.
    • Upload callbacks are not supported in append upload.

Use OSS SDKs

The following code provides examples on how to perform append upload by using OSS SDKs for common programming languages. For more information about how to perform append upload by using OSS SDKs for other programming languages, see Overview.

import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
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 {
        // In this example, the endpoint of the China (Hangzhou) region is used. Specify the actual endpoint. 
        String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
        // The AccessKey pair of an Alibaba Cloud account has permissions on all API operations. Using these credentials to perform operations in OSS is a high-risk operation. We recommend that you use a RAM user to call API operations or perform routine O&M. To create a RAM user, log on to the RAM console. 
        String accessKeyId = "yourAccessKeyId";
        String accessKeySecret = "yourAccessKeySecret";
        // Specify the name of the bucket. 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";

        // Create an OSSClient instance. 
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        try {
            ObjectMetadata meta = new ObjectMetadata();
            // Specify the type of content that you want to upload. 
            meta.setContentType("text/plain");
            // Specify the caching behavior of the web page for the object. 
            //meta.setCacheControl("no-cache");
            // Specify the name of the object when the object is downloaded. 
            //meta.setContentDisposition("attachment;filename=oss_download.txt");
            // Specify the encoding format for the content of the object. 
            //meta.setContentEncoding(OSSConstants.DEFAULT_CHARSET_NAME);
            // Specify the request header that is used to check whether the content of the received message is the same as the content of the sent message. 
            //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, the method is set to server-side encryption by using OSS-managed keys (SSE-OSS). 
            //meta.setServerSideEncryption(ObjectMetadata.AES_256_SERVER_SIDE_ENCRYPTION);
            // Specify the access control list (ACL) of the object. In this example, the ACL of the object is set to private. 
            //meta.setObjectAcl(CannedAccessControlList.Private);
            // Specify the storage class of the object. 
            //meta.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard);
            // You can add parameters whose names are prefixed with x-oss-meta-* when you call the AppendObject operation to create an appendable object. These parameters cannot be included in the requests when you append content to an existing appendable object. Parameters whose names are prefixed with x-oss-meta-* are considered as the metadata of the object. 
            //meta.setHeader("x-oss-meta-author", "Alice");

            // Configure multiple parameters by using AppendObjectRequest. 
            AppendObjectRequest appendObjectRequest = new AppendObjectRequest(bucketName, objectName, new ByteArrayInputStream(content1.getBytes()),meta);

            // Configure a single parameter by using AppendObjectRequest. 
            // Specify the bucket name. 
            //appendObjectRequest.setBucketName(bucketName);
            // Specify the object name. 
            //appendObjectRequest.setKey(objectName);
            // Specify the content that you want to append. You can choose InputStream or File. In this example, the content is set to InputStream. 
            //appendObjectRequest.setInputStream(new ByteArrayInputStream(content1.getBytes()));
            // Specify the content that you want to append. You can choose InputStream or File. In this example, the content is set to File. 
            //appendObjectRequest.setFile(new File("D:\\localpath\\examplefile.txt"));
            // Specify the metadata of the object. You can specify the metadata of an object only when you perform the first append operation on the object. 
            //appendObjectRequest.setMetadata(meta);

            // Perform the first append operation. 
            // Specify the position from which the append operation starts. 
            appendObjectRequest.setPosition(0L);
            AppendObjectResult appendObjectResult = ossClient.appendObject(appendObjectRequest);
            // Calculate the CRC-64 value of the object. The value is calculated based on the ECMA-182 specification. 
            System.out.println(appendObjectResult.getObjectCRC());

            // Perform the second append operation. 
            // NextPosition specifies the position from which the next append operation starts, which is the length of the object. 
            appendObjectRequest.setPosition(appendObjectResult.getNextPosition());
            appendObjectRequest.setInputStream(new ByteArrayInputStream(content2.getBytes()));
            appendObjectResult = ossClient.appendObject(appendObjectRequest);

            // Perform the third append operation. 
            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();
            }
        }
    }
}
 <?php
if (is_file(__DIR__ . '/../autoload.php')) {
    require_once __DIR__ . '/../autoload.php';
}
if (is_file(__DIR__ . '/../vendor/autoload.php')) {
    require_once __DIR__ . '/../vendor/autoload.php';
}

use OSS\OssClient;
use OSS\Core\OssException;

// Security risks may arise if you use the AccessKey pair of an Alibaba Cloud account to access OSS because the account has permissions on all API operations. We recommend that you use a RAM user to call API operations or perform routine operations and maintenance. To create a RAM user, log on to the RAM console. 
$accessKeyId = "yourAccessKeyId";
$accessKeySecret = "yourAccessKeySecret";
// In this example, the endpoint of the China (Hangzhou) region is used. Specify the endpoint based on your business requirements. 
$endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// Specify the name of the bucket. 
$bucket= "examplebucket";
// Specify the full path of the object. The full path of the object cannot contain the bucket name. 
$object = "exampleobject.txt";
// Specify the full paths of the local files to upload. By default, if you do not specify the full path of a local file, the local file is uploaded from the path of the project to which the sample program belongs. 
$filePath = "D:\\localpath\\examplefilea.txt";
$filePath1 = "D:\\localpath\\examplefileb.txt";
$filePath2 = "D:\\localpath\\examplefilec.txt";

try{
    $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint);
    // Perform the first append upload. 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 upload starts is the current length of the object. 
    $position = $ossClient->appendFile($bucket, $object, $filePath, 0);
    $position = $ossClient->appendFile($bucket, $object, $filePath1, $position);
    $position = $ossClient->appendFile($bucket, $object, $filePath2, $position);
} catch(OssException $e) {
    printf(__FUNCTION__ . ": FAILED\n");
    printf($e->getMessage() . "\n");
    return;
}
print(__FUNCTION__ . ": OK" . "\n");            
const OSS = require('ali-oss')

const client = new OSS({
  // Set yourRegion to the region in which the bucket is located. For example, if your bucket is located in the China (Hangzhou) region, set yourRegion to oss-cn-hangzhou. 
  region: 'yourRegion',
  // Security risks may arise if you use the AccessKey pair of an Alibaba Cloud account to access Object Storage Service (OSS) because the account has permissions on all API operations. We recommend that you use a RAM user to call API operations or perform routine operations and maintenance. To create a RAM user, log on to the RAM console. 
  accessKeyId: 'yourAccessKeyId',
  accessKeySecret: 'yourAccessKeySecret',
  // Specify the name of the bucket. Example: examplebucket. 
  bucket: 'examplebucket',
});

const headers = {
  // Specify the caching behavior of the web page when the object is downloaded. 
  'Cache-Control': 'no-cache',
  //Specify the name of the object when the object is downloaded.
  'Content-Disposition': 'oss_download.txt',
  // 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 request header that is used to check whether the content of the received message is the same as the content of the sent message. 
  // To obtain the value of the Content-MD5 header, calculate a 128-bit number based on the content of the message, except the headers. Then, encode the number in Base64. 
  'Content-MD5': 'ohhnqLBJFiKkPSBO1eNaUA==',
  // Specify the expiration time of the request. 
  'Expires': 'Fri, 31 Dec 2021 16:57:01 GMT',
  // Specify the server-side encryption method. In this example, the method is set to server-side encryption by using OSS-managed keys (SSE-OSS). 
  'x-oss-server-side-encryption': 'AES256',
  // Specify the content encoding format of the object. 
  'Content-Encoding': 'utf-8',
};

const meta = {
  'name': 'eliot',
  'age': '18',
}

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

  // Start the second append. 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();
# -*- coding: utf-8 -*-
import oss2

# Security risks may arise if you use the AccessKey pair of an Alibaba Cloud account to access Object Storage Service (OSS) because the account has permissions on all API operations. We recommend that you use a RAM user to call API operations or perform routine operations and maintenance. To create a RAM user, log on to the RAM console. 
auth = oss2.Auth('<yourAccessKeyId>', '<yourAccessKeySecret>')
# In this example, the endpoint of the China (Hangzhou) region is used. Specify the endpoint based on your business requirements. 
# Specify the name of the bucket. Example: examplebucket. 
bucket = oss2.Bucket(auth, 'https://oss-cn-hangzhou.aliyuncs.com', 'examplebucket')

# The following code provides an example on how to specify headers for the append upload: 
# headers = dict()
# Specify the caching behavior of the web page for the object. 
# headers['Cache-Control'] = 'no-cache'
# Specify the name of the object when the object is downloaded. 
# headers['Content-Disposition'] = 'oss_MultipartUpload.txt'
# Specify the encoding format for the content of the object. 
# headers['Content-Encoding'] = 'utf-8'
# Specify the request header that is used to check whether the message content is the same as the content of the message when it was sent. 
# headers['Content-MD5'] = 'ohhnqLBJFiKkPSBO1eNaUA=='
# Specify the expiration time. 
# headers['Expires'] = 'Wed, 08 Jul 2022 16:57:01 GMT'
# Specify the access control list (ACL) of the object. In this example, this parameter is set to OBJECT_ACL_PRIVATE, which indicates private. 
# headers['x-oss-object-acl'] = oss2.OBJECT_ACL_PRIVATE
# Specify whether to overwrite the object with the same name in the append upload. 
# headers['x-oss-forbid-overwrite'] = 'true'
# Specify the method that is used to encrypt objects on the OSS server. In this example, the method is set to server-side encryption by using OSS-managed keys (SSE-OSS) 
# headers[OSS_SERVER_SIDE_ENCRYPTION] = SERVER_SIDE_ENCRYPTION_AES256
# Specify the storage class of the object. 
# headers['x-oss-storage-class'] = oss2.BUCKET_STORAGE_CLASS_STANDARD
# You can add parameters whose names are prefixed with x-oss-meta- when you call the AppendObject operation to create an append object. These parameters cannot be included in the requests when you append content to the existing append objects. Parameters whose names are prefixed with x-oss-meta- are considered the metadata of the object. 
# headers['x-oss-meta-author'] = 'Alice'
# result = bucket.append_object(exampledir/exampleobject.txt, 0, 'content of first append', headers=headers)

# Set the position from which the first append operation starts to 0. 
# Specify the full path of the object. The full path of the object cannot contain the bucket name. Example: exampledir/exampleobject.txt. 
result = bucket.append_object('exampledir/exampleobject.txt', 0, 'content of first append')
# If you have appended content to the object, you can obtain the position from which the current append operation starts from the next_position field in the response returned by the last operation or by using the bucket.head_object method. 
bucket.append_object('<yourObjectName>', result.next_position, 'content of second append')        
using Aliyun.OSS;

// Set yourEndpoint to the endpoint of the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set yourEndpoint to https://oss-cn-hangzhou.aliyuncs.com. 
var endpoint = "yourEndpoint";
// Security risks may arise if you use the AccessKey pair of an Alibaba Cloud account to access OSS because the account has permissions on all API operations. We recommend that you use a RAM user to call API operations or perform routine O&M. To create a RAM user, log on to the RAM console. 
var accessKeyId = "yourAccessKeyId";
var accessKeySecret = "yourAccessKeySecret";
// Specify the name of the bucket. Example: examplebucket. 
var bucketName = "examplebucket";
// Specify the full path of the object. The full path cannot contain the bucket name. 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 full path of the local file, the local file is uploaded from the path of the project to which the sample program belongs. 
var localFilename = "D:\\localpath\\examplefile.txt";
// Create an OSSClient instance. 
var client = new OssClient(endpoint, accessKeyId, accessKeySecret);
// 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 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);
    }
    // Obtain the position for the next append operation 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);
}
// Specify the name of the bucket such as examplebucket, the full path of the object such as exampledir/exampleobject.txt, and the full path of the local file such as /storage/emulated/0/oss/examplefile.txt. 
// The full path of the object cannot contain the bucket name. 
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);

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

// Configure a callback function. 
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. 
    }
});
package main

import (
    "fmt"
    "os"
    "strings"
    "github.com/aliyun/aliyun-oss-go-sdk/oss"
)

func main() {
    // Create an OSSClient instance. 
    // Set yourEndpoint to the endpoint of the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set yourEndpoint to https://oss-cn-hangzhou.aliyuncs.com. Specify the endpoint based on your business requirements. 
    // Security risks may arise if you use the AccessKey pair of an Alibaba Cloud account to access Object Storage Service (OSS) because the account has permissions on all API operations. We recommend that you use a RAM user to call API operations or perform routine operations and maintenance. To create a RAM user, log on to the RAM console. 
    client, err := oss.New("yourEndpoint", "yourAccessKeyId", "yourAccessKeySecret")
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }

    // Specify the name of the bucket. Example: examplebucket. 
    bucket, err := client.Bucket("examplebucket")
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }

    // Specify the full path of the object. The full path of the object cannot contain the bucket name. Example: exampledir/exampleobject.txt. 
    objectName := "exampledir/exampleobject.txt"
    var nextPos int64 = 0
    // If the object is appended for the first time, the append position is 0. The position for the next append operation is included in the response. The position from which the next append operation starts is the current length of the object.     
    // Specify the expiration time. 
    expires := time.Date("2021, time.December, 10, 23, 0, 0, 0, time.UTC")
    option := []oss.Option{
        oss.Expires(expires),
        // Specify the caching behavior of the web page when the object is downloaded. 
        //oss.CacheControl("no-cache"),
        // Specify the name of the object when the object is downloaded. 
        //oss.ContentDisposition("attachment;filename=FileName.txt"),
        // Specify the encoding format for the content of the object. 
        //oss.ContentEncoding("gzip"),
        // Specify the storage class of the object. 
        //oss.ObjectStorageClass(oss.StorageStandard),
        // Specify the access control list (ACL) of the object. 
        //oss.ObjectACL(oss.ACLPrivate),
        // Specify the server-side encryption method. 
        //oss.ServerSideEncryption("AES256"),
        // You can add parameters whose names are prefixed with x-oss-meta- when you call the AppendObject operation to create an append object. These parameters cannot be included in the requests when you append content to an existing append object. Parameters whose names are prefixed with x-oss-meta- are considered the metadata of the object. 
        //oss.Meta("x-oss-meta-author", "Alice"),
    }


    nextPos, err = bucket.AppendObject(objectName, strings.NewReader("YourObjectAppendValue1"), nextPos,option...)
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }

    // If you have appended content to the object, you can obtain the position from which the current append operation starts from the X-Oss-Next-Append-Position field in the response returned by the last operation or by using the bucket.GetObjectDetailedMeta method. 
    //props, err := bucket.GetObjectDetailedMeta("objectName")
    //if err != nil {
    //    fmt.Println("Error:", err)
    //    os.Exit(-1)
    //}
    //nextPos, err = strconv.ParseInt(props.Get("X-Oss-Next-Append-Position"), 10, 64)
    //if err != nil {
    //    fmt.Println("Error:", err)
    //    os.Exit(-1)
    //}

    // Perform the second append operation. 
    nextPos, err = bucket.AppendObject(objectName, strings.NewReader("YourObjectAppendValue2"), nextPos)
    if err != nil {
        fmt.Println("Error:", err,"aaa")
        os.Exit(-1)
    }

    // You can perform append operations on an object for multiple times. 
}
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 the information about the account that is used to access OSS. */
    /* Security risks may arise if you use the AccessKey pair of an Alibaba Cloud account to access OSS because the account has permissions on all API operations. We recommend that you use a RAM user to call API operations or perform routine O&M. To create a RAM user, log on to the RAM console. */
    std::string AccessKeyId = "yourAccessKeyId";
    std::string AccessKeySecret = "yourAccessKeySecret";
    /* 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 = "https://oss-cn-hangzhou.aliyuncs.com";
    /* Specify the name of the bucket. Example: examplebucket. */
    std::string BucketName = "examplebucket";
    /* Specify the full path of the object. The full path cannot contain the bucket name. Example: exampledir/exampleobject.txt. */
    std::string ObjectName = "exampledir/exampleobject.txt";

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

    ClientConfiguration conf;
    OssClient client(Endpoint, AccessKeyId, AccessKeySecret, conf);

    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 operation 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;
        ShutdownSdk();
        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;
        ShutdownSdk();
        return -1;
    }

    /* Release resources such as networks. */
    ShutdownSdk();
    return 0;
}
#include "oss_api.h"
#include "aos_http_io.h"
/* The endpoint of the China (Hangzhou) region is used in this example. Specify the actual endpoint. */
const char *endpoint = "<yourEndpoint>";
/* Security risks may arise if you use the AccessKey pair of an Alibaba Cloud account to log on to OSS because the account has permissions on all API operations. We recommend that you use your RAM user's credentials to call API operations or perform routine operations and maintenance. To create a RAM user, log on to the RAM console. */
const char *access_key_id = "<yourAccessKeyId>";
const char *access_key_secret = "<yourAccessKeySecret>";
/* Configure the bucket name. */
const char *bucket_name = "<yourBucketName>";
/* Configure the object name. The object name indicates the complete path of the object excluding the bucket name. Example: example/folder/abc.jpg. */
const char *object_name = "<yourObjectName>";
const char *object_content = "More than just cloud.";
void init_options(oss_request_options_t *options)
{
    options->config = oss_config_create(options->pool);
    /* Use a char* string to initialize aos_string_t. */
    aos_str_set(&options->config->endpoint, endpoint);
    aos_str_set(&options->config->access_key_id, access_key_id);
    aos_str_set(&options->config->access_key_secret, access_key_secret);
    /* Specify whether to use CNAME. A value of 0 indicates that CNAME is not used. */
    options->config->is_cname = 0;
    /* Configure network parameters such as timeout periods. */
    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 networks and memory. */
    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 second parameter is NULL. This value indicates that the pool does not inherit any other memory pool. */
    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, which releases 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(
  endpoint: 'endpoint',
  access_key_id: 'AccessKeyId', access_key_secret: 'AccessKeySecret')

bucket = client.get_bucket('my-bucket')
# Create an appendable object.
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')
            

Use ossutil

For more information about how to perform append upload by using ossutil, see appendfromfile.

Use the RESTful API

If your business requires a high level of customization, you can directly call RESTful APIs. To directly call an API, you must include the signature calculation in your code. For more information, see AppendObject.