追加アップロードを使用すると、既存の追加可能オブジェクトの末尾にコンテンツを直接追加できます。
前提条件
バケットが作成されていること。詳細については、「バケットの作成」をご参照ください。背景情報
シンプルアップロードで作成されたオブジェクトは通常オブジェクト、マルチパートアップロードで作成されたオブジェクトはマルチパートオブジェクトです。アップロードが完了すると、これら 2 種類のオブジェクトのコンテンツは固定されます。読み取りはできますが、変更はできません。オブジェクトのコンテンツが変更された場合は、同じ名前のオブジェクトを再度アップロードして、既存のコンテンツを上書きする必要があります。
この制限があるため、これらの方法でビデオ監視システムや ApsaraVideo Live などのソースからリアルタイムのビデオストリームをアップロードする場合、ビデオストリームをより小さなチャンクに分割し、新しいオブジェクトとして継続的にアップロードすることしかできません。このアプローチには、次のデメリットがあります。
-
ソフトウェアアーキテクチャが複雑になります。ファイルのチャンク化などの詳細を管理する必要があります。
-
生成されたオブジェクトのリストなど、メタデータを保存する場所が必要です。その後、各リクエストはメタデータを繰り返し読み取り、新しいオブジェクトが生成されたかどうかを確認する必要があります。これにより、サーバーに大きな負荷がかかります。クライアントも毎回 2 つのネットワークリクエストを送信する必要があり、レイテンシーが増加する可能性があります。
-
オブジェクトをより小さなチャンクに分割すると、データ遅延を減らすことができます。しかし、多数の小さなオブジェクトは管理が複雑になります。オブジェクトをより大きなチャンクに分割すると、データ遅延が大幅に増加します。
アップロードされたビデオストリームのコンテンツをリアルタイムで更新するには、まずビデオをローカルで結合します。次に、Object Storage Service (OSS) が提供する追加アップロード (AppendObject) 機能を使用してビデオをアップロードできます。これにより、追加可能オブジェクトが作成されます。追加可能オブジェクトにはコンテンツを直接追加できます。追加されたデータは、各追加操作の直後に読み取り可能になります。
メリット
追加アップロードを使用すると、データが生成されるとすぐに同じオブジェクトにビデオデータをアップロードできます。クライアントは、オブジェクトの長さを定期的に取得し、以前に読み取った長さと比較するだけで済みます。新しい読み取り可能なデータが見つかった場合、クライアントは読み取り操作をトリガーして、新しくアップロードされたデータを取得します。この方法は、アーキテクチャを簡素化し、拡張性を向上させます。
制限事項
-
サイズ制限
オブジェクトサイズは 5 GB を超えることはできません。
操作の制限
-
追加アップロードを使用して、コールドアーカイブまたはディープコールドアーカイブストレージオブジェクトをアップロードすることはできません。
-
追加アップロードは、アップロードコールバックをサポートしていません。
バケットで ObjectWorm が有効になっている場合、追加アップロードは使用できません。また、既存の追加可能オブジェクトに対して ObjectWorm を有効にすることもできません。
-
注意事項
-
オブジェクトが存在しない場合、AppendObject API オペレーションを呼び出すと、追加可能オブジェクトが作成されます。
-
オブジェクトが既に存在する場合:
-
オブジェクトが追加可能オブジェクトであり、指定された追加位置が現在のオブジェクトの長さと等しい場合、コンテンツはオブジェクトの末尾に追加されます。
-
オブジェクトが追加可能オブジェクトであるが、指定された追加位置が現在のオブジェクトの長さと等しくない場合、PositionNotEqualToLength 例外がスローされます。
-
オブジェクトがシンプルアップロードを使用してアップロードされた通常オブジェクトなど、追加不可能なオブジェクトである場合、ObjectNotAppendable 例外がスローされます。
-
方法
Alibaba Cloud SDK の使用
以下のセクションでは、一般的な SDK を使用した追加アップロードのコード例を示します。他の 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";
// バケットが配置されているリージョンを指定します。たとえば、バケットが中国 (杭州) リージョンにある場合、リージョンを 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;
// バケットが配置されているリージョンのエンドポイントを指定します。たとえば、バケットが中国 (杭州) リージョンにある場合、エンドポイントを 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);
c.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);
}
// 次の追加操作が開始される位置をクエリし、2 回目の追加操作を実行します。
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);
/* char* 文字列で aos_string_t 型を初期化します。*/
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);
/* オプションを作成して初期化します。このパラメーターには、endpoint、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(®ion, "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 は、追加不可能なオブジェクトを追加可能なオブジェクトに直接変換することをサポートしていません。ただし、次の方法を使用して変換を実行できます。
-
AppendObject API オペレーションを使用して、新しい空の追加可能オブジェクトを作成します。
-
元のオブジェクトをダウンロードし、そのコンテンツを読み取ります。
-
AppendObject API オペレーションを使用して、新しく作成されたオブジェクトにコンテンツを追加します。
変換プロセスには、コンテンツの再読み取りと再アップロードが含まれます。変換が完了したら、オブジェクトの可用性を確認してください。