すべてのプロダクト
Search
ドキュメントセンター

Object Storage Service:Append upload

最終更新日:Dec 06, 2025

アペンドアップロードを使用すると、既存の追加可能オブジェクトの末尾にコンテンツを直接追加できます。

前提条件

バケットが作成されていること。詳細については、「バケットの作成」をご参照ください。

背景情報

シンプルアップロードで作成されたオブジェクトは通常オブジェクト、マルチパートアップロードで作成されたオブジェクトはマルチパートオブジェクトです。アップロードが完了すると、これら 2 種類のオブジェクトのコンテンツは固定され、読み取りのみ可能で、変更はできません。オブジェクトのコンテンツが変更された場合は、同じ名前のオブジェクトを再度アップロードして、既存のコンテンツを上書きする必要があります。

この制限のため、ビデオ監視システムや ApsaraVideo Live などのソースからリアルタイムのビデオストリームをアップロードする場合、これらの方法ではビデオストリームを小さな断片に分割し、新しいオブジェクトとして継続的にアップロードすることしかできません。このアプローチには、次のデメリットがあります。

  • ソフトウェアアーキテクチャが複雑になります。ファイルのチャンク化などの詳細を管理する必要があります。

  • 生成されたオブジェクトのリストなど、メタデータを保存する場所が必要です。その後、各リクエストはメタデータを繰り返し読み取り、新しいオブジェクトが生成されたかどうかを確認する必要があります。これにより、サーバーに大きな負荷がかかります。また、クライアントは毎回 2 つのネットワークリクエストを送信する必要があり、レイテンシーが増加する可能性があります。

  • オブジェクトをより小さな断片に分割すると、データレイテンシーを短縮できます。しかし、多数の小さなオブジェクトは管理が複雑になります。オブジェクトをより大きな断片に分割すると、データレイテンシーが大幅に増加します。

アップロードされたビデオストリームのコンテンツをリアルタイムで更新するには、まずビデオをローカルで連結します。次に、Object Storage Service (OSS) が提供するアペンドアップロード (AppendObject) 機能を使用してビデオをアップロードします。これにより、追加可能オブジェクトが作成されます。追加可能オブジェクトにはコンテンツを直接追加でき、追加されたデータは各追加操作の直後に読み取り可能になります。

メリット

アペンドアップロードを使用すると、ビデオデータが生成されるとすぐに同じオブジェクトにアップロードできます。クライアントは、オブジェクトの長さを定期的に取得し、以前に読み取った長さと比較するだけで済みます。新しい読み取り可能なデータが見つかった場合、クライアントは読み取り操作をトリガーして、新しくアップロードされたデータを取得します。この方法により、アーキテクチャが簡素化され、拡張性が向上します。

制限事項

  • サイズ制限

    オブジェクトサイズは 5 GB を超えることはできません。

  • 操作の制限

    • アペンドアップロードを使用して、コールドアーカイブまたはディープコールドアーカイブのオブジェクトをアップロードすることはできません。

    • アペンドアップロードはアップロードコールバックをサポートしていません。

注意事項

  • オブジェクトが存在しない場合、AppendObject API 操作を呼び出すと、追加可能オブジェクトが作成されます。

  • オブジェクトが既に存在する場合:

    • オブジェクトが追加可能オブジェクトであり、指定された追加位置が現在のオブジェクトの長さと等しい場合、コンテンツはオブジェクトの末尾に追加されます。

    • オブジェクトが追加可能オブジェクトであっても、指定された追加位置が現在のオブジェクトの長さと等しくない場合、PositionNotEqualToLength 例外がスローされます。

    • オブジェクトが、シンプルアップロードでアップロードされた通常オブジェクトなどの追加不可能なオブジェクトである場合、ObjectNotAppendable 例外がスローされます。

方法

Alibaba Cloud SDK の使用

以下のセクションでは、一般的な SDK (software development kit) を使用したアペンドアップロードのコード例を示します。他の SDK を使用したコード例については、「SDK の概要」をご参照ください。

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 {
        // 中国 (杭州) リージョンのエンドポイントを例として使用します。実際のエンドポイントを指定してください。
        String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
        // 環境変数からアクセス認証情報を取得します。サンプルコードを実行する前に、OSS_ACCESS_KEY_ID および OSS_ACCESS_KEY_SECRET 環境変数が設定されていることを確認してください。
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
        // バケット名を指定します (例: examplebucket)。
        String bucketName = "examplebucket";
        // オブジェクトのフルパスを指定します。フルパスにバケット名を含めることはできません。例: 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";
        // バケットが配置されているリージョンを指定します。たとえば、バケットが中国 (杭州) リージョンにある場合は、Region を cn-hangzhou に設定します。
        String region = "cn-hangzhou";

        // OSSClient インスタンスを作成します。
        // OSSClient インスタンスが不要になったら、shutdown メソッドを呼び出してリソースを解放します。
        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();
            // アップロードのコンテンツタイプを指定します。
            meta.setContentType("text/plain");
            // オブジェクトの Web ページのキャッシュ動作を指定します。
            //meta.setCacheControl("no-cache");
            // オブジェクトがダウンロードされるときの名前を指定します。
            //meta.setContentDisposition("attachment;filename=oss_download.txt");
            // オブジェクトのコンテンツエンコード形式を指定します。
            //meta.setContentEncoding(OSSConstants.DEFAULT_CHARSET_NAME);
            // このリクエストヘッダーは、メッセージの内容が送信された内容と一致するかどうかを確認するために使用されます。
            //meta.setContentMD5("ohhnqLBJFiKkPSBO1eNaUA==");
            // 有効期限を指定します。
            //try {
            //    meta.setExpirationTime(DateUtil.parseRfc822Date("Wed, 08 Jul 2022 16:57:01 GMT"));
            //} catch (ParseException e) {
            //    e.printStackTrace();
            //}
            // サーバーサイド暗号化方式を指定します。この例では、OSS マネージドキーによるサーバーサイド暗号化 (SSE-OSS) が使用されます。
            //meta.setServerSideEncryption(ObjectMetadata.AES_256_SERVER_SIDE_ENCRYPTION);
            // オブジェクトのアクセス権限を指定します。この例では、非公開のアクセス権限が指定されています。
            //meta.setObjectAcl(CannedAccessControlList.Private);
            // オブジェクトのストレージクラスを指定します。
            //meta.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard);
            // AppendObject の作成時に x-oss-meta-* を追加できます。後続の追加ではこのパラメーターを付与できません。x-oss-meta-* というプレフィックスを持つパラメーターを設定すると、そのパラメーターはメタデータと見なされます。
            //meta.setHeader("x-oss-meta-author", "Alice");

            // AppendObjectRequest を介して複数のパラメーターを設定します。
            AppendObjectRequest appendObjectRequest = new AppendObjectRequest(bucketName, objectName, new ByteArrayInputStream(content1.getBytes()),meta);

            // AppendObjectRequest を介して単一のパラメーターを設定します。
            // バケット名を設定します。
            //appendObjectRequest.setBucketName(bucketName);
            // オブジェクト名を設定します。
            //appendObjectRequest.setKey(objectName);
            // 追加するコンテンツを設定します。型は InputStream または File にすることができます。この例では、型は InputStream です。
            //appendObjectRequest.setInputStream(new ByteArrayInputStream(content1.getBytes()));
            // 追加するコンテンツを設定します。型は InputStream または File にすることができます。この例では、型は File です。
            //appendObjectRequest.setFile(new File("D:\\localpath\\examplefile.txt"));
            // ファイルのメタデータを指定します。これは最初の追加でのみ有効です。
            //appendObjectRequest.setMetadata(meta);

            // 最初の追加。
            // ファイルの追加位置を設定します。
            appendObjectRequest.setPosition(0L);
            AppendObjectResult appendObjectResult = ossClient.appendObject(appendObjectRequest);
            // ファイルの 64 ビット CRC 値。
            System.out.println(appendObjectResult.getObjectCRC());

            // 2 回目の追加。
            // nextPosition は、次のリクエストで提供されるべき位置、つまりファイルの現在の長さを示します。
            appendObjectRequest.setPosition(appendObjectResult.getNextPosition());
            appendObjectRequest.setInputStream(new ByteArrayInputStream(content2.getBytes()));
            appendObjectResult = ossClient.appendObject(appendObjectRequest);

            // 3 回目の追加。
            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({
  // バケットが配置されているリージョンに設定します。たとえば、バケットが中国 (杭州) リージョンにある場合は、リージョンを oss-cn-hangzhou に設定します。
  region: 'yourRegion',
  // 環境変数からアクセス認証情報を取得します。サンプルコードを実行する前に、OSS_ACCESS_KEY_ID および OSS_ACCESS_KEY_SECRET 環境変数が設定されていることを確認してください。
  accessKeyId: process.env.OSS_ACCESS_KEY_ID,
  accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET,
  authorizationV4: true,
  // バケット名を指定します。例: examplebucket
  bucket: 'examplebucket',
});

const headers = {    
  // オブジェクトのアクセス権限を指定します。
  'x-oss-object-acl': 'private',
  // オブジェクトのストレージクラスを指定します。
  'x-oss-storage-class': 'Standard',  
  // サーバーサイド暗号化方式を指定します。この例では、OSS マネージドキーによるサーバーサイド暗号化 (SSE-OSS) が使用されます。
  'x-oss-server-side-encryption': 'AES256',  
};

async function append () {
  // 最初の追加アップロードを実行します。戻り値は、次の追加操作の位置を示します。
  // objectName は、バケット名を含まないオブジェクトのフルパスを指定します。例: destfolder/examplefile.txt
  // localFile は、ファイル拡張子を含むローカルファイルのフルパスを指定します。例: /users/local/examplefile.txt
  let result = await client.append('objectName', 'localFile'
  // カスタムヘッダーとメタデータ。
  //,{headers} 
  )

  // 2 回目の追加アップロードを実行します。次の追加操作の位置は、この追加操作前のオブジェクトの長さ (Content-Length) です。
  result = await client.append('objectName', 'localFile', {
    position: result.nextAppendPosition
  })
}

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

// yourEndpoint をバケットが配置されているリージョンのエンドポイントに置き換えます。たとえば、バケットが中国 (杭州) リージョンにある場合は、エンドポイントを https://oss-cn-hangzhou.aliyuncs.com に設定します。
var endpoint = "yourEndpoint";
// 環境変数からアクセス認証情報を取得します。このサンプルコードを実行する前に、OSS_ACCESS_KEY_ID および OSS_ACCESS_KEY_SECRET 環境変数が設定されていることを確認してください。
var accessKeyId = Environment.GetEnvironmentVariable("OSS_ACCESS_KEY_ID");
var accessKeySecret = Environment.GetEnvironmentVariable("OSS_ACCESS_KEY_SECRET");
// バケット名を指定します。例: examplebucket
var bucketName = "examplebucket";
// オブジェクトのフルパスを指定します。フルパスにバケット名を含めることはできません。例: exampledir/exampleobject.txt
var objectName = "exampledir/exampleobject.txt";
// ローカルファイルのフルパスを指定します。例: D:\\localpath\\examplefile.txt。ローカルパスを指定しない場合、ファイルはサンプルプログラムが属するプロジェクトのローカルパスからアップロードされます。
var localFilename = "D:\\localpath\\examplefile.txt";
// バケットが配置されているリージョンを指定します。たとえば、バケットが中国 (杭州) リージョンにある場合は、リージョンを cn-hangzhou に設定します。
const string region = "cn-hangzhou";

// ClientConfiguration インスタンスを作成し、必要に応じてデフォルトのパラメーターを変更します。
var conf = new ClientConfiguration();

// 署名 V4 を使用します。
conf.SignatureVersion = SignatureVersion.V4;

// OssClient インスタンスを作成します。
var client = new OssClient(endpoint, accessKeyId, accessKeySecret, conf);
client.SetRegion(region);
// 最初の追加操作の位置は 0 です。戻り値は次の追加操作の位置です。後続の追加操作の位置は、追加前のオブジェクトの長さです。
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
        };
        // オブジェクトを追加します。
        var result = client.AppendObject(request);
        // オブジェクトの追加位置を設定します。
        position = result.NextAppendPosition;
        Console.WriteLine("Append object succeeded, next append position:{0}", position);
    }
    // 追加位置を取得し、オブジェクトを再度追加します。
    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);
}
// バケット名、オブジェクトのフルパス、ローカルファイルのフルパスを指定します。例: examplebucket、exampledir/exampleobject.txt、/storage/emulated/0/oss/examplefile.txt
// オブジェクトのフルパスにバケット名を含めることはできません。
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);

// 追加位置を設定します。
append.setPosition(0);

// コールバックを設定します。
append.setProgressCallback(new OSSProgressCallback<AppendObjectRequest>() {
    @Override
    public void onProgress(AppendObjectRequest request, long currentSize, long totalSize) {
        Log.d("AppendObject", "currentSize: " + currentSize + " totalSize: " + totalSize);
    }
});
// データを非同期で追加します。
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) {
        // 例外を処理します。
    }
});
OSSAppendObjectRequest * append = [OSSAppendObjectRequest new];
// 必須フィールドを設定します。`bucketName` はバケットの名前を指定します。`objectKey` は `objectName` と同等で、データを追加したいオブジェクトのフルパスを指定します。パスにはファイル拡張子を含める必要があります (例: `abc/efg/123.jpg`)。
append.bucketName = @"<bucketName>";
append.objectKey = @"<objectKey>";
// 最初の追加アップロードの位置を指定します。
append.appendPosition = 0; 
NSString * docDir = [self getDocumentDirectory];
append.uploadingFileURL = [NSURL fileURLWithPath:@"<yourLocalFilePath>"];
// 以下のフィールドはオプションです。
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)
{
    /* OSS アカウント情報を初期化します。*/
            
    /* yourEndpoint をバケットが配置されているリージョンのエンドポイントに設定します。たとえば、バケットが中国 (杭州) リージョンにある場合は、エンドポイントを https://oss-cn-hangzhou.aliyuncs.com に設定します。*/
    std::string Endpoint = "yourEndpoint";
    /* yourRegion をバケットが配置されているリージョンに設定します。たとえば、バケットが中国 (杭州) リージョンにある場合は、リージョンを cn-hangzhou に設定します。*/
    std::string Region = "yourRegion";
    /* バケット名を指定します (例: examplebucket)。*/
    std::string BucketName = "examplebucket";
    /* オブジェクトのフルパスを指定します。フルパスにバケット名を含めることはできません。例: exampledir/exampleobject.txt */
    std::string ObjectName = "exampledir/exampleobject.txt";

    /* ネットワークリソースを初期化します。*/
    InitializeSdk();

    ClientConfiguration conf;
    conf.signatureVersion = SignatureVersionType::V4;
    /* 環境変数からアクセス認証情報を取得します。このサンプルコードを実行する前に、OSS_ACCESS_KEY_ID および OSS_ACCESS_KEY_SECRET 環境変数が設定されていることを確認してください。*/
    auto credentialsProvider = std::make_shared<EnvironmentVariableCredentialsProvider>();
    OssClient client(Endpoint, credentialsProvider, conf);
    client.SetRegion(Region);

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

    /* 最初の追加操作の位置は 0 です。戻り値は次の追加操作の位置を示します。後続の追加操作の位置は、追加前のオブジェクトの長さです。*/
    std::shared_ptr<std::iostream> content1 = std::make_shared<std::stringstream>();
    *content1 <<"Thank you for using Alibaba Cloud Object Storage Service!";
    AppendObjectRequest request(BucketName, ObjectName, content1, meta);
    request.setPosition(0L);

    /* オブジェクトに初めてデータを追加します。*/
    auto result = client.AppendObject(request);

    if (!result.isSuccess()) {
        /* 例外を処理します。*/
        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 Alibaba Cloud Object Storage Service!";
    auto position = result.result().Length();
    AppendObjectRequest appendObjectRequest(BucketName, ObjectName, content2);
    appendObjectRequest.setPosition(position);

    /* オブジェクトに 2 回目のデータを追加します。*/
    auto outcome = client.AppendObject(appendObjectRequest);

    if (!outcome.isSuccess()) {
        /* 例外を処理します。*/
        std::cout << "AppendObject fail" <<
        ",code:" << outcome.error().Code() <<
        ",message:" << outcome.error().Message() <<
        ",requestId:" << outcome.error().RequestId() << std::endl;
        return -1;
    }

    /* ネットワークリソースを解放します。*/
    ShutdownSdk();
    return 0;
}
#include "oss_api.h"
#include "aos_http_io.h"
/* yourEndpoint をバケットが配置されているリージョンのエンドポイントに設定します。たとえば、中国 (杭州) リージョンの場合は、エンドポイントを https://oss-cn-hangzhou.aliyuncs.com に設定します。*/
const char *endpoint = "yourEndpoint";

/* バケット名を指定します。例: examplebucket */
const char *bucket_name = "examplebucket";
/* オブジェクトのフルパスを指定します。フルパスにバケット名を含めることはできません。例: exampledir/exampleobject.txt */
const char *object_name = "exampledir/exampleobject.txt";
const char *object_content = "More than just cloud.";
/* yourRegion をバケットが配置されているリージョンに設定します。たとえば、中国 (杭州) リージョンの場合は、リージョンを cn-hangzhou に設定します。*/
const char *region = "yourRegion";
void init_options(oss_request_options_t *options)
{
    options->config = oss_config_create(options->pool);
    /* aos_string_t 型を char* 文字列で初期化します。*/
    aos_str_set(&options->config->endpoint, endpoint);
    /* 環境変数からアクセス認証情報を取得します。このサンプルコードを実行する前に、OSS_ACCESS_KEY_ID および OSS_ACCESS_KEY_SECRET 環境変数が設定されていることを確認してください。*/    
    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"));
    // 以下の 2 つのパラメーターを設定します。
    aos_str_set(&options->config->region, region);
    options->config->signature_version = 4;
    /* CNAME が使用されるかどうかを指定します。0 は CNAME が使用されないことを示します。*/
    options->config->is_cname = 0;
    /* タイムアウト期間などのネットワークパラメーターを設定します。*/
    options->ctl = aos_http_controller_create(options->pool, 0);
}
int main(int argc, char *argv[])
{
    /* プログラムエントリで aos_http_io_initialize メソッドを呼び出して、ネットワークやメモリなどのグローバルリソースを初期化します。*/
    if (aos_http_io_initialize(NULL, 0) != AOSE_OK) {
        exit(1);
    }
    /* メモリ管理のためのメモリプールは apr_pool_t と同等です。実装コードは apr ライブラリにあります。*/
    aos_pool_t *pool;
    /* 新しいメモリプールを作成します。2 番目のパラメーターは NULL で、新しいメモリプールが他のメモリプールから継承しないことを示します。*/
    aos_pool_create(&pool, NULL);
    /* オプションを作成して初期化します。このパラメーターには、エンドポイント、access_key_id、access_key_secret、is_cname、curl などのグローバル設定情報が含まれます。*/
    oss_request_options_t *oss_client_options;
    /* メモリプール内のオプションにメモリを割り当てます。*/
    oss_client_options = oss_request_options_create(pool);
    /* クライアントオプション oss_client_options を初期化します。*/
    init_options(oss_client_options);
    /* パラメーターを初期化します。*/
    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);
    /* 追加の開始位置を取得します。*/
    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);
    }
    /* オブジェクトを追加します。*/
    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");
    }
    /* メモリプールを解放します。これにより、リクエスト中にリソースに割り当てられたメモリが解放されます。*/
    aos_pool_destroy(pool);
    /* 以前に割り当てられたグローバルリソースを解放します。*/
    aos_http_io_deinitialize();
    return 0;
}
require 'aliyun/oss'

client = Aliyun::OSS::Client.new(
  # 中国 (杭州) リージョンを例として使用します。実際のリージョンを指定してください。
  endpoint: 'https://oss-cn-hangzhou.aliyuncs.com',
  # 環境変数からアクセス認証情報を取得します。サンプルコードを実行する前に、OSS_ACCESS_KEY_ID および OSS_ACCESS_KEY_SECRET 環境変数が設定されていることを確認してください。
  access_key_id: ENV['OSS_ACCESS_KEY_ID'],
  access_key_secret: ENV['OSS_ACCESS_KEY_SECRET']
)

# バケット名を指定します (例: examplebucket)。
bucket = client.get_bucket('examplebucket')
# オブジェクトのフルパスを指定します。フルパスにバケット名を含めることはできません。
bucket.append_object('my-object', 0)

# ファイルの末尾にコンテンツを追加します。
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"
)

// グローバル変数を定義します。
var (
	region     string
	bucketName string
	objectName string
)

// init 関数は、コマンドラインパラメーターを初期化するために使用されます。
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() {
	// コマンドラインパラメーターを解析します。
	flag.Parse()

	// アペンドアップロードの初期位置を定義します。
	var (
		position = int64(0)
	)

	// バケット名が空かどうかを確認します。
	if len(bucketName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, bucket name required")
	}

	// リージョンが空かどうかを確認します。
	if len(region) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, region required")
	}

	// オブジェクト名が空かどうかを確認します。
	if len(objectName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, object name required")
	}

	// デフォルト設定をロードし、認証情報プロバイダーとリージョンを設定します。
	cfg := oss.LoadDefaultConfig().
		WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()).
		WithRegion(region)

	// OSS クライアントを作成します。
	client := oss.NewClient(cfg)

	// 追加するコンテンツを定義します。
	content := "hi append object"

	// AppendObject リクエストを作成します。
	request := &oss.AppendObjectRequest{
		Bucket:   oss.Ptr(bucketName),
		Key:      oss.Ptr(objectName),
		Position: oss.Ptr(position),
		Body:     strings.NewReader(content),
	}

	// AppendObject リクエストを実行し、結果を処理します。
	// 最初のアペンドアップロードの位置は 0 です。戻り値には、次のアペンドアップロードの位置が含まれます。
	result, err := client.AppendObject(context.TODO(), request)
	if err != nil {
		log.Fatalf("failed to append object %v", err)
	}

	// 2 番目の AppendObject リクエストを作成します。
	request = &oss.AppendObjectRequest{
		Bucket:   oss.Ptr(bucketName),
		Key:      oss.Ptr(objectName),
		Position: oss.Ptr(result.NextPosition), // 最初の AppendObject リクエストの戻り値から NextPosition を取得します。
		Body:     strings.NewReader("hi append object"),
	}

	// 2 番目の AppendObject リクエストを実行し、結果を処理します。
	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

# コマンドライン引数パーサーを作成します。
parser = argparse.ArgumentParser(description="append object sample")

# コマンドライン引数を追加します。
# --region: OSS バケットが配置されているリージョンを指定します。
parser.add_argument('--region', help='The region in which the bucket is located.', required=True)
# --bucket: 操作対象のバケットの名前を指定します。
parser.add_argument('--bucket', help='The name of the bucket.', required=True)
# --endpoint: OSS サービスへのアクセスに使用されるドメイン名を指定するオプションのパラメーターです。
parser.add_argument('--endpoint', help='The domain names that other services can use to access OSS')
# --key: OSS 内のオブジェクト (ファイル) のキーを指定します。
parser.add_argument('--key', help='The name of the object.', required=True)

def main():
    # コマンドライン引数を解析します。
    args = parser.parse_args()

    # OSS に必要な認証情報を環境変数からロードします。
    credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider()

    # SDK が提供するデフォルト設定を使用して設定オブジェクトを作成します。
    cfg = oss.config.load_default()

    # 認証情報プロバイダーを以前に作成したオブジェクトに設定します。
    cfg.credentials_provider = credentials_provider

    # ユーザーの入力に基づいて OSS クライアントのリージョンを設定します。
    cfg.region = args.region

    # ユーザーがカスタムエンドポイントを提供した場合、設定を更新します。
    if args.endpoint is not None:
        cfg.endpoint = args.endpoint

    # 上記の設定を使用して OSS クライアントインスタンスを作成します。
    client = oss.Client(cfg)

    # 追加するデータを定義します。
    data1 = b'hello'
    data2 = b' world'

    # データを初めて追加します。
    result = client.append_object(oss.AppendObjectRequest(
        bucket=args.bucket,  # 宛先バケットを指定します。
        key=args.key,  # オブジェクトのキーを指定します。
        position=0,  # 追加を開始する位置。最初は 0 です。
        body=data1,  # 追加するデータ。
    ))

    # 最初の追加操作の結果を出力します。
    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},' 
    )

    # データを 2 回目に追加します。
    result = client.append_object(oss.AppendObjectRequest(
        bucket=args.bucket,  # 宛先バケットを指定します。
        key=args.key,  # オブジェクトのキーを指定します。
        position=result.next_position,  # 前回の追加操作の次の位置から開始します。
        body=data2,  # 追加するデータ。
    ))

    # 2 回目の追加操作の結果を出力します。
    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},'
    )

# このスクリプトが直接実行された場合、main 関数を呼び出します。
if __name__ == "__main__":
    main()
<?php

// 依存ライブラリをロードするために autoload ファイルを導入します。
require_once __DIR__ . '/../vendor/autoload.php';

use AlibabaCloud\Oss\V2 as Oss;

// コマンドラインパラメーターを定義し、説明します。
$optsdesc = [
    "region" => ['help' => 'The region in which the bucket is located.', 'required' => True], // (必須) バケットが配置されているリージョンを指定します。
    "endpoint" => ['help' => 'The domain names that other services can use to access OSS.', 'required' => False], // (オプション) OSS へのアクセス用のエンドポイントを指定します。
    "bucket" => ['help' => 'The name of the bucket', 'required' => True], // (必須) バケットの名前を指定します。
    "key" => ['help' => 'The name of the object', 'required' => True], // (必須) オブジェクトの名前を指定します。
];

// 説明を getopt が必要とする長いオプションのリストに変換します。
// 各パラメーターの末尾にコロン (:) を追加して、値が必要であることを示します。
$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])) {
        $help = $value['help']; // パラメーターのヘルプ情報を取得します。
        echo "Error: the following arguments are required: --$key, $help" . PHP_EOL;
        exit(1); // 必須パラメーターが欠落している場合はプログラムを終了します。
    }
}

// コマンドラインパラメーターから解析された値を対応する変数に割り当てます。
$region = $options["region"]; // バケットが配置されているリージョン。
$bucket = $options["bucket"]; // バケットの名前。
$key = $options["key"];       // オブジェクトの名前。

// 環境変数からアクセス認証情報をロードします。
// EnvironmentVariableCredentialsProvider を使用して、環境変数から AccessKey ID と AccessKey Secret を取得します。
$credentialsProvider = new Oss\Credentials\EnvironmentVariableCredentialsProvider();

// SDK のデフォルト設定を使用します。
$cfg = Oss\Config::loadDefault();
$cfg->setCredentialsProvider($credentialsProvider); // 認証情報プロバイダーを指定します。
$cfg->setRegion($region); // バケットが配置されているリージョンを指定します。
if (isset($options["endpoint"])) {
    $cfg->setEndpoint($options["endpoint"]); // エンドポイントが提供されている場合は指定します。
}

// OSSClient インスタンスを作成します。
$client = new Oss\Client($cfg);

// 追加したいコンテンツを指定します。
$data='Hello Append Object'; // サンプルデータを実際のコンテンツに置き換えてください。

// 特定のオブジェクトにデータを追加するための AppendObjectRequest オブジェクトを作成します。
$request = new Oss\Models\AppendObjectRequest(bucket: $bucket, key: $key);
$request->body = Oss\Utils::streamFor($data); // HTTP リクエストボディがバイナリストリームであることを指定します。
$request->position = 0; // 最初の追加操作が開始する位置を 0 に設定します。

// アペンドアップロード操作を実行します。
$result = $client->appendObject($request);

// 結果を表示します。
// HTTP ステータスコードとリクエスト ID を表示して、リクエストが成功したかどうかを確認します。
printf(
    'status code:' . $result->statusCode . PHP_EOL . // HTTP ステータスコード。たとえば、HTTP ステータスコード 200 はリクエストが成功したことを示します。
    'request id:' . $result->requestId . PHP_EOL .    // リクエスト ID。リクエストのデバッグや追跡に使用されます。
    'next append position:' . $result->nextPosition . PHP_EOL // 次の追加操作が開始する位置を指定します。
);

ossutil コマンドラインインターフェイスの使用

ossutil コマンドラインインターフェイス (CLI) を使用して、オブジェクトを追加およびアップロードできます。ossutil をインストールするには、「ossutil のインストール」をご参照ください。

次のコマンドは、`exampleobject` オブジェクトに文字列としてコンテンツを追加します。

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

このコマンドの詳細については、「append-object」をご参照ください。

関連 API

上記の方法は API 操作に基づいています。プログラムに高度なカスタマイズ要件がある場合は、REST API リクエストを直接送信できます。REST API リクエストを直接送信するには、署名を計算するコードを手動で記述する必要があります。詳細については、「AppendObject」をご参照ください。

よくある質問

アペンドアップロードにファイルタイプの制限はありますか?

いいえ。アペンドアップロードはバイナリストリームのみを認識し、ファイルタイプに関する要件はありません。

追加不可能なファイルをどうすれば追加可能なファイルに変換できますか?

OSS は、追加不可能なオブジェクトを追加可能なオブジェクトに直接変換することをサポートしていません。ただし、次の方法を使用して変換を実行できます。

  1. AppendObject API 操作を使用して、新しい空の追加可能オブジェクトを作成します。

  2. 元のオブジェクトをダウンロードし、そのコンテンツを読み取ります。

  3. AppendObject API 操作を使用して、新しく作成されたオブジェクトにコンテンツを追加します。

重要

変換プロセスには、コンテンツの再読み取りと再アップロードが含まれます。変換が完了したら、オブジェクトの可用性を確認してください。