OSS は AWS S3 API と互換性があります。AWS SDK を使用して OSS にアクセスするために、コードを変更する必要はありません。OSS の Endpoint と アクセス資格情報 を設定するだけで済みます。
Endpoint: S3 互換のパブリック Endpoint (
https://s3.oss-{region}.aliyuncs.com) または内部 Endpoint (https://s3.oss-{region}.aliyuncs-internal.com) を使用します。{region}を実際のリージョン ID (例:cn-hangzhou) に置き換えます。リージョンの完全なリストについては、「リージョンとエンドポイント」をご参照ください。重要アクセス資格情報: 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"
awsconfig "github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/s3"
)
// Go v2 では、大きなファイル (5 MB 以上) をアップロードすると、チャンクエンコーディングが自動的に有効になり、失敗の原因となります。大きなファイルをアップロードするには、Go SDK v1 を使用してください。
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) では、Security Token Service (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://oss-cn-hangzhou.aliyuncs.com", ""))
.build();
// ビジネスロジック
s3Client.putObject("my-bucket", "test.txt", "Hello OSS");iOS
モバイルアプリケーション (iOS) では、Security Token Service (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://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 の Signature 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 の Signature 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 Signature V4: OSS は AWS Signature V4 アルゴリズムを完全にサポートしています。
Signature V2: これは boto3 の特殊なケースです。SDK 実装の制限により、Signature V2 を使用する必要があります。
互換性: boto3 を除き、他のすべての SDK は Signature V4 を使用して OSS にアクセスできます。
新規プロジェクトのバージョン選択:
シナリオ | 選択可能なソリューション | 理由 |
新規 Python プロジェクト | boto3 + Signature V2 | boto3 は現在 OSS Signature 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 アクセス資格情報は完全に別のシステムであり、相互に使用することはできません。コード内の aws_access_key_id や aws_secret_access_key などのパラメーターを確認してください。OSS コンソールで作成した AccessKey ID と AccessKey Secret を使用していることを確認してください。
2 番目に多い原因は、サーバーの時計のずれです。S3 署名アルゴリズムには、署名にタイムスタンプが含まれています。OSS サーバーは、リクエスト時間と自身のサーバー時間の差を検証します。サーバーの時計が標準時から 15 分以上ずれている場合、すべてのリクエストは拒否されます。date -u コマンドを実行して、サーバーの UTC 時刻を確認できます。時刻が正しくない場合は、ntpdate またはシステム時刻同期サービスを使用して修正してください。
3 番目の原因は、Endpoint 設定が正しくないことです。Endpoint が s3.amazonaws.com などの AWS ドメイン名を指している場合や、間違った OSS リージョンを指定している場合、署名の計算は失敗します。OSS Endpoint の標準フォーマットは https://oss-{region}.aliyuncs.com です。Endpoint のリージョンは、バケットが配置されているリージョン (oss-cn-hangzhou や oss-cn-beijing など) と一致する必要があります。
boto3 を使用する場合、別の特定の原因があります。signature_version='s3' が設定されていない場合、boto3 はデフォルトの Signature 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 を実行します。コマンドがバケットの内容を正常にリスト表示した場合、アクセス資格情報と Endpoint は正しいです。これは、問題がコードの設定にあることを示しています。
バケットアクセスエラー
NoSuchBucket または AccessDenied エラーは、指定されたバケットにアクセスできないことを示します。最も一般的な原因は、Endpoint とバケットのリージョンが一致しないことです。
各 OSS バケットは、cn-hangzhou や cn-beijing などの特定のリージョンに属しています。バケットにアクセスする場合、Endpoint はバケットのリージョンに対応するドメイン名を使用する必要があります。たとえば、バケットが杭州リージョンにある場合、Endpoint は oss-cn-hangzhou.aliyuncs.com です。北京リージョンの Endpoint である oss-cn-beijing.aliyuncs.com は使用できません。この動作は、クロスリージョンアクセスを許可し、自動リダイレクトを実行する AWS S3 とは異なります。OSS はクロスリージョンアクセスをサポートしていません。不正な Endpoint を使用すると、NoSuchBucket エラーが発生します。
2 番目の原因は、RAM 権限設定の問題です。OSS AccessKey に関連付けられている RAM ユーザーがターゲットバケットにアクセスする権限を持っているかどうかを確認します。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 Multipart Upload API に基づいています。OSS はこれらの API と完全に互換性があるため、コードを変更せずに直接使用できます。