All Products
Search
Document Center

Object Storage Service:Append upload (Harmony SDK)

Last Updated:Mar 20, 2026

Append upload lets you add content to an existing appendable object without replacing it — useful for streaming logs, live data feeds, or any scenario where you write data incrementally. This topic explains how to use the appendObject method in OSS SDK for Harmony 2.0.

Prerequisites

Before you begin, make sure you have:

  • An OSS bucket (see Regions and endpoints for region and endpoint formats)

  • Credentials from Security Token Service (STS): AccessKey ID, AccessKey secret, and security token

  • The required permissions (see Permissions)

How it works

When you call appendObject:

  • If the object does not exist, OSS creates a new appendable object and writes the data to it.

  • If the object exists and is appendable, OSS appends the data at the specified position. The position must equal the current object length; otherwise, OSS returns a PositionNotEqualToLength error.

  • If the object exists but is not appendable, OSS returns an ObjectNotAppendable error.

For the first append, omit the position parameter. For each subsequent append, read the next position from the x-oss-next-append-position response header and pass it as position.

Permissions

Alibaba Cloud accounts have full permissions by default. RAM users and RAM roles have no permissions by default and must be granted access through a RAM Policy or bucket policy.

APIActionDescription
AppendObjectoss:PutObjectRequired to append data to an object
AppendObjectoss:PutObjectTaggingRequired when you set object tags via the x-oss-tagging header during append upload

Append a string

The following example appends a string to an object. On the first call, if the object does not exist, OSS creates it as an appendable object.

import Client, { RequestError } from '@aliyun/oss';

const client = new Client({
  accessKeyId: '<your-access-key-id>',       // AccessKey ID from STS
  accessKeySecret: '<your-access-key-secret>', // AccessKey secret from STS
  securityToken: '<your-security-token>',     // Security token from STS
  region: 'oss-cn-hangzhou',                  // Region where the bucket is located
});

const bucket = '<your-bucket-name>';
const key = '<your-object-name>';

const appendString = async () => {
  try {
    const res = await client.appendObject({
      bucket,
      key,
      data: 'hello world',
      // Omit `position` on the first append; OSS creates the object and returns the next position.
    });
    console.log(JSON.stringify(res));
  } catch (err) {
    if (err instanceof RequestError) {
      console.log('code:', err.code);
      console.log('message:', err.message);
      console.log('requestId:', err.requestId);
      console.log('status:', err.status);
      console.log('ec:', err.ec);
    } else {
      console.log('unknown error:', err);
    }
  }
};

appendString();

Replace the placeholders with your actual values:

PlaceholderDescriptionExample
<your-access-key-id>AccessKey ID from STSLTAI5tXxx
<your-access-key-secret>AccessKey secret from STSxXxXxX
<your-security-token>Security token from STS
<your-bucket-name>Name of the bucketmy-bucket
<your-object-name>Name of the object to append tologs/app.log

Append a local file

Use fileIo from HarmonyOS @kit.CoreFileKit to open a local file and pass the file handle as data. Always close the file in the finally block.

import Client, { RequestError } from '@aliyun/oss';
import { fileIo as fs } from '@kit.CoreFileKit';

const client = new Client({
  accessKeyId: '<your-access-key-id>',
  accessKeySecret: '<your-access-key-secret>',
  securityToken: '<your-security-token>',
  region: 'oss-cn-hangzhou',
});

const bucket = '<your-bucket-name>';
const key = '<your-object-name>';

const appendFile = async () => {
  const file = await fs.open('<your-file-path>', fs.OpenMode.READ_ONLY);

  try {
    const res = await client.appendObject({
      bucket,
      key,
      data: file,
    });
    console.log(JSON.stringify(res));
  } catch (err) {
    if (err instanceof RequestError) {
      console.log('code:', err.code);
      console.log('message:', err.message);
      console.log('requestId:', err.requestId);
      console.log('status:', err.status);
      console.log('ec:', err.ec);
    } else {
      console.log('unknown error:', err);
    }
  } finally {
    await fs.close(file); // Always close the file handle
  }
};

appendFile();

Replace <your-file-path> with the absolute path to your local file, for example /data/storage/logs/app.log.

Append multiple data blocks

For sequential appends, read x-oss-next-append-position from each response and pass it as position in the next call.

import Client, { RequestError, EHeaderKey } from '@aliyun/oss';

const client = new Client({
  accessKeyId: '<your-access-key-id>',
  accessKeySecret: '<your-access-key-secret>',
  securityToken: '<your-security-token>',
  region: 'oss-cn-hangzhou',
});

const bucket = '<your-bucket-name>';
const key = '<your-object-name>';

const appendMultiple = async () => {
  try {
    // First append — omit `position` to create the appendable object
    const res = await client.appendObject({
      bucket,
      key,
      data: 'first chunk data',
    });
    console.log(JSON.stringify(res));

    // Read the next append position from the response header
    const nextAppendPosition = Number(
      res.origRes.headers[EHeaderKey.X_OSS_NEXT_APPEND_POSITION]
    );

    // Second append — pass `position` to write at the correct offset
    const res1 = await client.appendObject({
      bucket,
      key,
      data: 'second chunk data',
      position: nextAppendPosition,
    });
    console.log(JSON.stringify(res1));
  } catch (err) {
    if (err instanceof RequestError) {
      console.log('code:', err.code);
      console.log('message:', err.message);
      console.log('requestId:', err.requestId);
      console.log('status:', err.status);
      console.log('ec:', err.ec);
    } else {
      console.log('unknown error:', err);
    }
  }
};

appendMultiple();

Error reference

Error codeCause
PositionNotEqualToLengthThe position value does not match the current object length. Read x-oss-next-append-position from the previous response and retry.
ObjectNotAppendableThe object exists but was not created with append upload. Only appendable objects support AppendObject.

What's next