All Products
Search
Document Center

Object Storage Service:Perform append upload by using OSS SDK for PHP

Last Updated:Mar 20, 2026

Append upload lets you add content to the end of an existing object incrementally — suited for use cases like log collection, streaming data writes, and any workflow where content is generated in chunks over time. This topic shows how to perform append upload using the OSS SDK for PHP V2.

For the complete runnable example, see the GitHub sample.

Prerequisites

Before you begin, make sure you have:

How it works

When you call AppendObject:

  • If the target object does not exist, OSS creates an appendable object and writes the content starting at position 0.

  • If the target object exists and is appendable, OSS appends the content at the position you specify. The position must equal the current length of the object; otherwise, OSS returns a PositionNotEqualToLength error.

  • If the target object exists but is not appendable (for example, it was uploaded using simple upload), OSS returns an ObjectNotAppendable error.

Each successful response includes a nextPosition field. Pass this value as the position parameter in your next AppendObject call.

Usage notes

  • The sample code uses region ID cn-hangzhou (China (Hangzhou)) with a public endpoint. To access OSS from other Alibaba Cloud services in the same region, use an internal endpoint. For supported regions and endpoints, see Regions and endpoints.

  • Access credentials are read from environment variables at runtime.

Append content to an object

First append

Set position to 0 for the first append. OSS creates the appendable object if it does not already exist.

<?php

// Load the SDK autoloader.
require_once __DIR__ . '/../vendor/autoload.php';

use AlibabaCloud\Oss\V2 as Oss;

// Define and parse command-line parameters.
$optsdesc = [
    "region"   => ['help' => 'The region where the bucket is located.', 'required' => true],
    "endpoint" => ['help' => 'The endpoint for accessing OSS.', 'required' => false],
    "bucket"   => ['help' => 'The name of the bucket.', 'required' => true],
    "key"      => ['help' => 'The name of the object.', 'required' => true],
];

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

foreach ($optsdesc as $key => $value) {
    if ($value['required'] === true && empty($options[$key])) {
        echo "Error: --$key is required. " . $value['help'] . PHP_EOL;
        exit(1);
    }
}

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

// Load credentials from environment variables.
$credentialsProvider = new Oss\Credentials\EnvironmentVariableCredentialsProvider();

// Configure the SDK client.
$cfg = Oss\Config::loadDefault();
$cfg->setCredentialsProvider($credentialsProvider);
$cfg->setRegion($region);
if (isset($options["endpoint"])) {
    $cfg->setEndpoint($options["endpoint"]);
}

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

// First append: position must be 0.
$data    = 'Hello Append Object';
$request = new Oss\Models\AppendObjectRequest(bucket: $bucket, key: $key);
$request->body     = Oss\Utils::streamFor($data);
$request->position = 0;

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

printf(
    "status code: %s\n" .
    "request id: %s\n" .
    "next append position: %s\n",
    $result->statusCode,
    $result->requestId,
    $result->nextPosition   // Use this value as the position for the next append.
);

Subsequent appends

Pass the nextPosition value from the previous response as the position for each subsequent call.

// Use the nextPosition returned by the previous AppendObject call.
$nextPosition = $result->nextPosition;

$moreData    = 'More content to append';
$nextRequest = new Oss\Models\AppendObjectRequest(bucket: $bucket, key: $key);
$nextRequest->body     = Oss\Utils::streamFor($moreData);
$nextRequest->position = $nextPosition;

$nextResult = $client->appendObject($nextRequest);

printf(
    "status code: %s\n" .
    "request id: %s\n" .
    "next append position: %s\n",
    $nextResult->statusCode,
    $nextResult->requestId,
    $nextResult->nextPosition
);
If the position value does not match the current object length, OSS returns PositionNotEqualToLength. Always use the nextPosition from the latest successful response to keep the position in sync.

References