All Products
Search
Document Center

Object Storage Service:Append upload

Last Updated:Jan 30, 2024

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 Object Storage Service (OSS) as separated objects. Simple upload and multipart upload in this scenario have the following disadvantages:

  • You need to have a complex architecture to handle aspects such as object splitting.

  • You need to reserve storage capacity to store object metadata, such as the list of uploaded objects. Each request involves metadata queries to check whether a new object is uploaded. In this case, the client must send two requests for each upload, which increases network latency and the workload on the server.

  • If the streams are split into a small number of parts, the network latency is low, but object management becomes more complex. If the streams are split into a large number of parts, the network latency significantly increases.

If you want to update the video streams of an uploaded object in real time, you can perform local video merging and call AppendObject to upload the video content. Objects that are uploaded by calling AppendObject are 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.

  • Operations

    • You cannot perform append upload to append content to a Cold Archive or Deep Cold Archive object.

    • Appendable objects cannot be copied. However, you can modify the metadata of appendable objects.

    • Upload callbacks are not supported in append upload.

Usage notes

  • If the object to which you want to append content does not exist, an appendable object is created when you call the AppendObject operation.

  • If the object to which you want to append content exists:

    • If the object is an appendable object and the specified position from which the append operation starts is equal to the current object size, the object is appended to the end of the object.

    • If the object is an appendable object and the specified position from which the append operation starts is not equal to the current object size, the PositionNotEqualToLength error is returned.

    • If the object is not an appendable object, the ObjectNotAppendable error is returned.

Procedure

Use OSS SDKs

The following sample 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.common.auth.*;
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 your actual endpoint. 
        String 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. 
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
        // Specify the name of the bucket. Example: examplebucket. 
        String bucketName = "examplebucket";
        // Specify the full path of the object. Do not include the bucket name in the full path. 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, credentialsProvider);

        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 SSE-OSS. 
            //meta.setServerSideEncryption(ObjectMetadata.AES_256_SERVER_SIDE_ENCRYPTION);
            // Specify the 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 name of the bucket. 
            //appendObjectRequest.setBucketName(bucketName);
            // Specify the name of the object. 
            //appendObjectRequest.setKey(objectName);
            // Specify the content that you want to append. Two types of content are supported: InputStream and File. In this example, the content is set to InputStream. 
            //appendObjectRequest.setInputStream(new ByteArrayInputStream(content1.getBytes()));
            // Specify the content that you want to append. Two types of content are supported: InputStream and File. In this example, the content is set to File. 
            //appendObjectRequest.setFile(new File("D:\\localpath\\examplefile.txt"));
            // Specify the object metadata. 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 standard. 
            System.out.println(appendObjectResult.getObjectCRC());

            // Start the second append. 
            // 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;

// 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. 
$accessKeyId = getenv("OSS_ACCESS_KEY_ID");
$accessKeySecret = getenv("OSS_ACCESS_KEY_SECRET");
// In this example, the endpoint of the China (Hangzhou) region is used. Specify your actual endpoint. 
$endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// Specify the name of the bucket. 
$bucket= "examplebucket";
// Specify the full path of the object. Do not include the bucket name in the full path. 
$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 operation. 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({
  // 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,
  // 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();
# -*- coding: utf-8 -*-
import oss2

# 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. 
auth = oss2.Auth('<yourAccessKeyId>', '<yourAccessKeySecret>')
# In this example, the endpoint of the China (Hangzhou) region is used. Specify your actual endpoint. 
# 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 content of the received message is the same as the content of the sent message. 
# 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, the ACL is set to OBJECT_ACL_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 server-side encryption method. In this example, SSE-OSS is specified for server-side encryption. 
# 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 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 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. Do not include the bucket name in the full path. 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 bucket.head_object. 
bucket.append_object('<yourObjectName>', result.next_position, 'content of second append')        
using Aliyun.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. 
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 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 you perform append upload to create an appendable object, the position from which the append operation starts is 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. 
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);
}
// 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. 
// 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);

// Specify 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() {
    /// 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. 
    provider, err := oss.NewEnvironmentVariableCredentialsProvider()
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }

    // Create an OSSClient instance. 
    // 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. Specify your actual endpoint. 
    client, err := oss.New("yourEndpoint", "", "", oss.SetCredentialsProvider(&provider))
    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. Do not include the bucket name in the full path. Example: exampledir/exampleobject.txt. 
    objectName := "exampledir/exampleobject.txt"
    var nextPos int64 = 0
    // If the object is appended for the first time, the position from which the append operation starts 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 of the request. 
    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 it is downloaded. 
        //oss.ContentDisposition("attachment;filename=FileName.txt"),
        // Specify the content encoding format of the object. 
        //oss.ContentEncoding("gzip"),
        // Specify the storage class of the object. 
        //oss.ObjectStorageClass(oss.StorageStandard),
        // Specify the ACL of the object. 
        //oss.ObjectACL(oss.ACLPrivate),
        // Specify the server-side encryption method. 
        //oss.ServerSideEncryption("AES256"),
        // When you call the AppendObject operation to create an appendable object, you can add parameters whose names are prefixed with x-oss-meta-*. These parameters cannot be included in the request in which you append content to an existing appendable 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 by using one of the following methods: X-Oss-Next-Append-Position in the response returned by the last append operation and bucket.GetObjectDetailedMeta. 
    //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 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 = "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. 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;
    /* 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);

    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.";
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 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')

Use ossutil

You can use ossutil to perform append upload. For more information, see appendfromfile.

Use the OSS 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.

FAQ

Does append upload have file type limits?

No, append upload has no file type limits. Append upload uses binary streams to append data.