Object Storage Service (OSS) は AWS S3 API と互換性があります。コードを変更することなく、AWS SDK を使用して OSS にアクセスできます。そのためには、OSS のエンドポイントとアクセス認証情報を設定します。
エンドポイント:S3 互換のパブリックエンドポイント (
https://s3.oss-{region}.aliyuncs.com) または内部ネットワークエンドポイント (https://s3.oss-{region}-internal.aliyuncs.com) を使用します。{region}は、cn-hangzhouなどの実際のリージョン ID に置き換えてください。リージョンの完全なリストについては、「リージョンとエンドポイント」をご参照ください。重要コンプライアンスとセキュリティを向上させるためのポリシーの変更により、2025 年 3 月 20 日より、新規 OSS ユーザーは、中国本土リージョンにある OSS バケットでデータ API 操作を実行するために、カスタムドメイン名を使用する (CNAME ドメイン名) 必要があります。これらの操作では、デフォルトのパブリックエンドポイントは制限されます。影響を受ける操作の完全なリストについては、公式発表をご参照ください。HTTPS 経由でデータにアクセスする場合、カスタムドメインに有効な SSL 証明書をバインドする必要があります。コンソールでは HTTPS が適用されるため、これは OSS コンソールへのアクセスには必須です。
アクセス認証情報:Resource Access Management (RAM) で OSS のアクセス権限を持つ AccessKey を作成します。
Java
SDK 2.x
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.S3Configuration;
import java.net.URI;
S3Client s3Client = S3Client.builder()
.endpointOverride(URI.create("https://s3.oss-cn-hangzhou.aliyuncs.com"))
.region(Region.AWS_GLOBAL)
.serviceConfiguration(
S3Configuration.builder()
.pathStyleAccessEnabled(false)
.chunkedEncodingEnabled(false)
.build()
)
.build();SDK 1.x
import com.amazonaws.client.builder.AwsClientBuilder.EndpointConfiguration;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
.withEndpointConfiguration(new EndpointConfiguration(
"https://s3.oss-cn-hangzhou.aliyuncs.com",
"cn-hangzhou"))
.withPathStyleAccessEnabled(false)
.withChunkedEncodingDisabled(false)
.build();SDK 1.x では、getObject から返される S3ObjectInputStream で close() を呼び出すと、未読のデータが即座に破棄されます。ストリームを閉じる前に、データを完全に読み取る必要があります。
S3Object object = s3Client.getObject("my-bucket", "file.txt");
InputStream input = object.getObjectContent();
byte[ ] data = IOUtils.toByteArray(input);
input.close();Python
import boto3
from botocore.config import Config
s3 = boto3.client(
's3',
endpoint_url='https://s3.oss-cn-hangzhou.aliyuncs.com',
config=Config(
signature_version='s3',
s3={'addressing_style': 'virtual'}
)
)
Node.js
SDK v3
import { S3Client } from '@aws-sdk/client-s3';
const client = new S3Client({
endpoint: 'https://s3.oss-cn-hangzhou.aliyuncs.com',
region: 'cn-hangzhou'
});SDK v2
const AWS = require('aws-sdk');
const s3 = new AWS.S3({
endpoint: 'https://s3.oss-cn-hangzhou.aliyuncs.com',
region: 'cn-hangzhou'
});Go
SDK v2
import (
"context"
"github.com/aws/aws-sdk-go-v2/aws"
awsconfig "github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/s3"
)
cfg, _ := awsconfig.LoadDefaultConfig(context.TODO(),
awsconfig.WithEndpointResolverWithOptions(
aws.EndpointResolverWithOptionsFunc(func(service, region string, options ...interface{}) (aws.Endpoint, error) {
return aws.Endpoint{
URL: "https://s3.oss-cn-hangzhou.aliyuncs.com",
}, nil
}),
),
)
client := s3.NewFromConfig(cfg)SDK v1
import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/s3"
)
sess := session.Must(session.NewSessionWithOptions(session.Options{
Config: aws.Config{
Endpoint: aws.String("https://s3.oss-cn-hangzhou.aliyuncs.com"),
Region: aws.String("cn-hangzhou"),
},
SharedConfigState: session.SharedConfigEnable,
}))
svc := s3.New(sess).NET
SDK 3.x
using Amazon.S3;
var config = new AmazonS3Config
{
ServiceURL = "https://s3.oss-cn-hangzhou.aliyuncs.com"
};
var client = new AmazonS3Client(config);SDK 2.x
using Amazon.S3;
var config = new AmazonS3Config
{
ServiceURL = "https://s3.oss-cn-hangzhou.aliyuncs.com"
};
var client = new AmazonS3Client(config);PHP
SDK 3.x
<?php
require_once __DIR__ . '/vendor/autoload.php';
use Aws\S3\S3Client;
$s3Client = new S3Client([
'version' => '2006-03-01',
'region' => 'cn-hangzhou',
'endpoint' => 'https://s3.oss-cn-hangzhou.aliyuncs.com'
]);SDK 2.x
<?php
require_once __DIR__ . '/vendor/autoload.php';
use Aws\S3\S3Client;
$s3Client = S3Client::factory([
'version' => '2006-03-01',
'region' => 'cn-hangzhou',
'base_url' => 'https://s3.oss-cn-hangzhou.aliyuncs.com'
]);Ruby
SDK 3.x
require 'aws-sdk-s3'
s3 = Aws::S3::Client.new(
endpoint: 'https://s3.oss-cn-hangzhou.aliyuncs.com',
region: 'cn-hangzhou'
)SDK 2.x
require 'aws-sdk'
s3 = AWS::S3::Client.new(
s3_endpoint: 's3.oss-cn-hangzhou.aliyuncs.com',
region: 'cn-hangzhou',
s3_force_path_style: false
)
C++
SDK バージョン 1.7.68 以降が必要です。
#include <aws/s3/S3Client.h>
#include <aws/core/client/ClientConfiguration.h>
Aws::Client::ClientConfiguration config;
config.endpointOverride = "s3.oss-cn-hangzhou.aliyuncs.com";
config.region = "cn-hangzhou";
Aws::S3::S3Client s3_client(config);ブラウザ
フロントエンド Web アプリケーションでは、Security Token Service (STS) の一時的な認証情報を使用する必要があります。クライアントに永続的な AccessKey をハードコーディングしないでください。サーバーサイドで AssumeRole 操作を呼び出して一時的な認証情報を取得し、クライアントに返します。詳細については、「STS の一時的な認証情報を使用した OSS へのアクセス」をご参照ください。
import { S3Client } from '@aws-sdk/client-s3';
// サーバーから STS の一時的な認証情報を取得します。
async function getSTSCredentials() {
const response = await fetch('https://your-server.com/api/sts-token');
return await response.json();
}
// 一時的な認証情報で S3 クライアントを初期化します。
const client = new S3Client({
region: 'cn-hangzhou',
endpoint: 'https://s3.oss-cn-hangzhou.aliyuncs.com',
credentials: async () => {
const creds = await getSTSCredentials();
return {
accessKeyId: creds.accessKeyId,
secretAccessKey: creds.secretAccessKey,
sessionToken: creds.securityToken,
expiration: new Date(creds.expiration)
};
}
});Android
モバイルアプリケーション (Android) では、STS の一時的な認証情報を使用する必要があります。クライアントに永続的な AccessKey をハードコーディングしないでください。サーバーサイドで AssumeRole 操作を呼び出して一時的な認証情報を取得し、クライアントに返します。詳細については、「STS の一時的な認証情報を使用した OSS へのアクセス」をご参照ください。
import com.amazonaws.auth.AWSCredentialsProvider;
import com.amazonaws.auth.BasicSessionCredentials;
import com.amazonaws.client.builder.AwsClientBuilder.EndpointConfiguration;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3Client;
// サーバーから STS の一時的な認証情報を取得するための認証情報プロバイダーを実装します。
public class OSSCredentialsProvider implements AWSCredentialsProvider {
@Override
public AWSCredentials getCredentials() {
// サーバーから STS の一時的な認証情報を取得します。
// https://your-server.com/api/sts-token にリクエストします。
String accessKeyId = fetchFromServer("accessKeyId");
String secretKeyId = fetchFromServer("secretKeyId");
String securityToken = fetchFromServer("securityToken");
return new BasicSessionCredentials(accessKeyId, secretKeyId, securityToken);
}
@Override
public void refresh() {
// 認証情報をリフレッシュします。
}
}
// S3 クライアントを作成します。
AmazonS3 s3Client = AmazonS3Client.builder()
.withCredentials(new OSSCredentialsProvider())
.withEndpointConfiguration(new EndpointConfiguration(
"https://s3.oss-cn-hangzhou.aliyuncs.com", ""))
.build();
// ビジネスロジック
s3Client.putObject("my-bucket", "test.txt", "Hello OSS");iOS
モバイルアプリケーション (iOS) では、STS の一時的な認証情報を使用する必要があります。クライアントに永続的な AccessKey をハードコーディングしないでください。サーバーサイドで AssumeRole 操作を呼び出して一時的な認証情報を取得し、クライアントに返します。詳細については、「STS の一時的な認証情報を使用した OSS へのアクセス」をご参照ください。
#import <AWSS3/AWSS3.h>
// 認証情報プロバイダーを実装します。
@interface OSSCredentialsProvider : NSObject <AWSCredentialsProvider>
@end
@implementation OSSCredentialsProvider
- (AWSTask<AWSCredentials *> *)credentials {
return [[AWSTask taskWithResult:nil] continueWithBlock:^id(AWSTask *task) {
// サーバーから STS の一時的な認証情報を取得します。
NSString *accessKey = [self fetchFromServer:@"accessKeyId"];
NSString *secretKey = [self fetchFromServer:@"secretKeyId"];
NSString *sessionToken = [self fetchFromServer:@"securityToken"];
AWSCredentials *credentials = [[AWSCredentials alloc]
initWithAccessKey:accessKey
secretKey:secretKey
sessionKey:sessionToken
expiration:[NSDate dateWithTimeIntervalSinceNow:3600]];
return [AWSTask taskWithResult:credentials];
}];
}
@end
// S3 クライアントを設定します。
AWSEndpoint *endpoint = [[AWSEndpoint alloc] initWithURLString:@"https://s3.oss-cn-hangzhou.aliyuncs.com"];
AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc]
initWithRegion:AWSRegionUnknown
endpoint:endpoint
credentialsProvider:[[OSSCredentialsProvider alloc] init]];
[AWSS3 registerS3WithConfiguration:configuration forKey:@"OSS"];
AWSS3 *s3 = [AWSS3 S3ForKey:@"OSS"];
// ビジネスロジック
AWSS3PutObjectRequest *request = [AWSS3PutObjectRequest new];
request.bucket = @"my-bucket";
request.key = @"test.txt";
request.body = [@"Hello OSS" dataUsingEncoding:NSUTF8StringEncoding];
[[s3 putObject:request] continueWithBlock:^id(AWSTask *task) {
if (task.error) {
NSLog(@"Error: %@", task.error);
} else {
NSLog(@"Success");
}
return nil;
}];よくある質問
アップロードの失敗:InvalidArgument: aws-chunked encoding is not supported
現象:ファイルをアップロードする際に、以下のエラーが表示されます。
InvalidArgument: aws-chunked encoding is not supported with the specified x-amz-content-sha256 value根本原因:
これは、AWS SDK を使用して OSS にアクセスする際に最もよく発生する問題です。OSS は AWS Signature V4 アルゴリズムをサポートしていますが、転送エンコーディングに違いがあります。
AWS S3 は、デフォルトでチャンクエンコーディングを使用して大きなファイルを転送します。
OSS は、チャンクエンコーディングを使用した転送をサポートしていません。
原因:
一部の SDK の Signature V4 実装は、チャンクエンコーディングに依存しています。
Python (boto3):Signature V4 はチャンクエンコーディングを強制するため、無効にできません。Signature V2 に切り替える必要があります。
Java:設定でチャンクエンコーディングを無効にできます。
Go/Node.js:デフォルトではチャンクエンコーディングは使用されません。特別な処理は不要です。
SDK 別のソリューション:
SDK | ソリューション | 理由 |
Python (boto3) | Signature V2 を使用: | boto3 の Signature V4 実装はチャンクエンコーディングに関連付けられており、無効にできません。 |
Java 1.x | Signature V4 + | チャンクエンコーディングは無効にできます。 |
Java 2.x | Signature V4 + | チャンクエンコーディングは無効にできます。 |
Go v1 | Signature V4 | デフォルトではチャンクエンコーディングを使用しません。 |
Go v2 | Signature V4。大きなファイルのアップロードには Manager に注意してください。 | Manager 機能はチャンクエンコーディングを使用する場合があります。 |
Node.js v3 | Signature V4 | デフォルトではチャンクエンコーディングを使用しません。 |
Python の例:修正前と修正後:
# 不正な設定 (boto3 の V4 実装はチャンクエンコーディングを使用)
s3 = boto3.client('s3',
endpoint_url='https://oss-cn-hongkong.aliyuncs.com',
config=Config(signature_version='v4'))
# 正しい設定 (boto3 は V2 署名を使用)
s3 = boto3.client('s3',
endpoint_url='https://oss-cn-hongkong.aliyuncs.com',
config=Config(signature_version='s3')) # V2 署名は boto3 のための安定したソリューションです技術的な詳細:
OSS V4 署名は AWS Signature Version 4 仕様に準拠しており、以下の要件があります。
リクエストヘッダーに
x-oss-content-sha256: UNSIGNED-PAYLOADが含まれていること。Transfer-Encoding: chunkedメソッドが使用されていないこと。
ほとんどの SDK は設定によって互換性をサポートしています。しかし、boto3 の Signature V4 実装はチャンクエンコーディングと密接に結合しているため、boto3 では Signature V2 を使用する必要があります。
SDK と署名バージョンの選択
バージョン選択のリファレンス:
言語 | SDK バージョン | 署名バージョン | 設定に関する注意事項 |
Python | 最新の boto3 バージョン | Signature V2 ( | boto3 の V4 実装は OSS と互換性がありません。 |
Java 1.x | 最新の 1.x | Signature V4 | チャンクエンコーディングを無効にする必要があります。 |
Java 2.x | 最新の 2.x | Signature V4 | チャンクエンコーディングを無効にする必要があります。 |
Node.js | v3 | Signature V4 (デフォルト) | - |
Go v1 | 最新の v1 | Signature V4 (デフォルト) | - |
Go v2 | 最新の v2 | Signature V4 (デフォルト) | 大きなファイルのアップロードに関する Manager の考慮事項 |
署名バージョンの詳細:
OSS V4 署名:OSS は AWS Signature V4 アルゴリズムを完全にサポートしています。
V2 署名:SDK の実装上の制限により、boto3 には Signature V2 が必要です。
互換性:boto3 を除き、他のすべての SDK は Signature V4 を使用して OSS にアクセスできます。
新規プロジェクトのバージョン選択:
シナリオ | 選択可能なソリューション | 理由 |
新規 Python プロジェクト | boto3 + Signature V2 | boto3 は現在 OSS V4 をサポートしていません。 |
新規 Java プロジェクト | Java 2.x + Signature V4 | パフォーマンスが向上します。 |
新規 Node.js プロジェクト | v3 + Signature V4 | - |
新規 Go プロジェクト | Go v1 + Signature V4 | 推奨されます。 |
既存プロジェクトの移行 | 現在の SDK バージョンを維持します。 | 変更によるリスクを最小限に抑えます。 |
署名エラー:SignatureDoesNotMatch
SignatureDoesNotMatch エラーが発生することがあります。このエラーは、サーバーサイドで計算された署名が、クライアントから提供された署名と一致しないことを示します。
最も一般的な原因は、コード内で OSS の AccessKey の代わりに AWS の AccessKey を使用していることです。AWS のアクセス認証情報と OSS のアクセス認証情報は 2 つの別個のシステムであり、相互に交換して使用することはできません。コード内の aws_access_key_id や aws_secret_access_key などのパラメーターを確認してください。OSS コンソールで作成した AccessKey ID と AccessKey Secret を使用していることを確認してください。
2 番目に多い原因は、サーバーのクロックドリフトです。S3 署名アルゴリズムには、署名にタイムスタンプが含まれています。OSS サーバーサイドは、リクエスト時刻とサーバー時刻の差を検証します。サーバーのクロックが標準時から 15 分以上ずれている場合、すべてのリクエストは拒否されます。date -u コマンドでサーバーの UTC 時刻を確認できます。時刻が正しくない場合は、ntpdate またはシステムの時刻同期サービスを使用して修正してください。
3 番目の原因は、エンドポイント設定が正しくないことです。エンドポイントが s3.amazonaws.com などの AWS ドメイン名を指している場合や、間違った OSS リージョンを使用している場合、署名計算は失敗します。OSS エンドポイントの標準フォーマットは https://oss-{region}.aliyuncs.com です。リージョンは、oss-cn-hangzhou や oss-cn-beijing など、バケットが配置されているリージョンと一致する必要があります。
もう 1 つの潜在的な原因は、boto3 の使用に特有のものです。signature_version='s3' を設定しない場合、boto3 はデフォルトの V4 署名アルゴリズムを使用するため、署名計算が失敗します。正しい boto3 の設定には、Config(signature_version='s3') パラメーターを含める必要があります。
設定を検証する簡単な方法は、ossutil コマンドラインインターフェイスを使用することです。次のコマンドを実行します:ossutil ls oss://your-bucket --access-key-id <key> --access-key-secret <secret> --endpoint oss-cn-hangzhou.aliyuncs.com。コマンドがバケットの内容を正常にリスト表示した場合、アクセス認証情報とエンドポイントは正しいです。問題は、コードの設定にある可能性が高いです。
バケットアクセスエラー
NoSuchBucket または AccessDenied エラーは、指定されたバケットにアクセスできないことを示します。最も一般的な原因は、エンドポイントとバケットのリージョンが一致しないことです。
各 OSS バケットは、cn-hangzhou や cn-beijing などの特定のリージョンに属します。バケットにアクセスする際、エンドポイントはバケットのリージョンと一致する必要があります。たとえば、バケットが杭州リージョンにある場合、エンドポイントは oss-cn-hangzhou.aliyuncs.com です。北京リージョンのエンドポイント oss-cn-beijing.aliyuncs.com を使用することはできません。リージョン間のアクセスを許可し、自動リダイレクトを実行する AWS S3 とは異なり、OSS はリージョン間のアクセスをサポートしていません。不正なエンドポイントを使用すると、NoSuchBucket エラーが発生します。
2 番目の原因は、RAM 権限設定の問題です。OSS AccessKey に関連付けられた RAM ユーザーが、ターゲットバケットへのアクセス権限を持っているかどうかを確認してください。OSS コンソールの RAM 管理ページで、ユーザーに oss:ListObjects、oss:GetObject、oss:PutObject などの必要な権限が付与されていることを確認します。
3 番目の原因は、バケットの命名規則に関連しています。OSS は、仮想ホストスタイル (bucket-name.oss-cn-hangzhou.aliyuncs.com) とパススタイル (oss-cn-hangzhou.aliyuncs.com/bucket-name) の 2 つの URL スタイルをサポートしています。仮想ホストスタイルを使用する場合、バケット名は DNS 命名規則に準拠する必要があり、アンダースコアを含めることはできません。バケット名にアンダースコアが含まれている場合は、SDK 設定でパススタイルを使用するか、準拠した名前で新しいバケットを作成する必要があります。
パフォーマンスの最適化
大きなファイルのアップロードとダウンロードは、オブジェクトストレージアプリケーションの一般的な要件です。AWS SDK は、OSS にも有効な複数の転送アクセラレーションメカニズムを提供します。
Python の boto3 を使用する場合、TransferConfig を使用してマルチパートアップロードのパラメーターを設定できます。ファイルが設定されたしきい値より大きい場合、boto3 は自動的にファイルを複数のパートに分割し、同時にアップロードします。これにより、転送速度が大幅に向上します。multipart_threshold パラメーターは、マルチパートアップロードを有効にするためのファイルサイズのしきい値を指定します。max_concurrency は同時アップロードスレッド数を指定し、multipart_chunksize は各パートのサイズを指定します。これらのパラメーターを正しく設定すると、100 MB を超える大きなファイルのアップロード速度が数倍に向上する可能性があります。
Java SDK を使用する場合、TransferManager クラスは、マルチパートアップロード、同時転送、自動リトライなどの機能を提供します。TransferManager はファイルサイズに基づいて最適な転送戦略を自動的に選択するため、マルチパートロジックを手動で処理する必要がありません。
Go SDK を使用する場合、PutObject を直接呼び出す代わりに、s3manager.Uploader を呼び出す必要があります。Uploader には、同時マルチパートアップロード機能が組み込まれており、大きなファイルを自動的に分割して同時アップロードし、失敗したアップロードのリトライロジックを処理します。
Node.js SDK を使用する場合、@aws-sdk/lib-storage パッケージの Upload クラスを使用できます。このクラスはストリーミングアップロードをサポートしています。ファイルの読み取り中にアップロードを開始できるため、メモリ使用量が削減されます。上記の Node.js セクションに例が記載されています。
これらの転送アクセラレーションメカニズムはすべて、S3 マルチパートアップロード API に基づいています。OSS はこの API と完全に互換性があるため、コードを変更することなくこれらのメカニズムを直接使用できます。