デフォルトでは、Object Storage Service (OSS) バケット内のファイルは非公開であり、バケットのオーナーのみがアップロードできます。ただし、バケットのオーナーは、特定のファイルの署名付き URL を生成して、一時的なアップロード権限を付与できます。この署名付き URL を持つユーザーは誰でも、URL の有効期間内にファイルをアップロードできます。この機能は、パートナーに契約書のアップロードを許可したり、ユーザーにプロフィール写真のアップロードを許可したりするなどのシナリオで役立ちます。
注意事項
このトピックでは、中国 (杭州) リージョンのパブリックエンドポイントを使用します。同じリージョン内の他の Alibaba Cloud サービスから OSS にアクセスするには、内部エンドポイントを使用します。サポートされているリージョンとエンドポイントの詳細については、「リージョンとエンドポイント」をご参照ください。
署名付き URL の生成に権限は必要ありません。ただし、サードパーティが署名付き URL を使用してファイルを正常にアップロードできるのは、URL を生成したユーザーが
oss:PutObject権限を持っている場合に限られます。権限の付与方法の詳細については、「RAM ユーザーへのカスタム権限の付与」をご参照ください。署名付き URL は、FormData 形式でのアップロードをサポートしていません。FormData を使用してデータをアップロードするには、OSS フォームアップロードを使用します。
コンプライアンスとセキュリティを向上させるためのポリシー変更により、2025 年 3 月 20 日以降、新規の OSS ユーザーは、中国本土リージョンにある OSS バケットでデータ API 操作を実行するために、カスタムドメイン名 (CNAME ドメイン名) を使用する必要があります。デフォルトのパブリックエンドポイントは、これらの操作では制限されます。影響を受ける操作の完全なリストについては、公式発表をご参照ください。HTTPS 経由でデータにアクセスする場合は、カスタムドメインに有効な SSL 証明書をバインドする必要があります。これは、コンソールが HTTPS を強制するため、OSS コンソールへのアクセスには必須です。
プロセスの概要
署名付き URL を使用してファイルをアップロードするプロセスは次のとおりです。
署名付き URL を使用した単一ファイルのアップロード
バケットのオーナーが PUT リクエスト用の署名付き URL を生成します。
説明SDK を使用して生成された署名付き URL の最大有効期間は 7 日間です。セキュリティトークンサービス (STS) トークンを使用して署名付き URL を生成する場合、最大有効期間は 43,200 秒 (12 時間) です。
Java
SDK の詳細については、「Java で署名付き URL を使用してファイルをアップロード」をご参照ください。
import com.aliyun.oss.*; import com.aliyun.oss.common.auth.*; import com.aliyun.oss.common.comm.SignVersion; import com.aliyun.oss.model.GeneratePresignedUrlRequest; import java.net.URL; import java.util.*; import java.util.Date; public class GetSignUrl { public static void main(String[] args) throws Throwable { // この例では、中国 (杭州) リージョンのパブリックエンドポイントを使用します。実際のエンドポイントを指定してください。 String endpoint = "https://oss-cn-hangzhou.aliyuncs.com"; // 環境変数からアクセス認証情報を取得します。サンプルコードを実行する前に、OSS_ACCESS_KEY_ID および OSS_ACCESS_KEY_SECRET 環境変数が設定されていることを確認してください。 EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider(); // バケット名を指定します (例: examplebucket)。 String bucketName = "examplebucket"; // オブジェクトの完全なパスを指定します (例: exampleobject.txt)。オブジェクトの完全なパスにバケット名を含めることはできません。 String objectName = "exampleobject.txt"; // バケットが配置されているリージョンを指定します。たとえば、バケットが中国 (杭州) リージョンにある場合、リージョンを 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(); URL signedUrl = null; try { // 生成された署名付き URL の有効期限をミリ秒単位で指定します。この例では、有効期限を 1 時間に設定します。 Date expiration = new Date(new Date().getTime() + 3600 * 1000L); // 署名付き URL を生成します。 GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucketName, objectName, HttpMethod.PUT); // 有効期限を設定します。 request.setExpiration(expiration); // HTTP PUT リクエスト用の署名付き URL を生成します。 signedUrl = ossClient.generatePresignedUrl(request); // 署名付き URL を出力します。 System.out.println("signed url for putObject: " + signedUrl); } 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()); } } }Go
SDK の詳細については、「Go で署名付き URL を使用してファイルをアップロード」をご参照ください。
package main import ( "context" "flag" "log" "time" "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() // バケット名が空かどうかを確認します。 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) // PutObject リクエスト用の署名付き URL を生成します。 result, err := client.Presign(context.TODO(), &oss.PutObjectRequest{ Bucket: oss.Ptr(bucketName), Key: oss.Ptr(objectName), //ContentType: oss.Ptr("text/txt"), // URL に含まれる ContentType パラメーターの値が、リクエストで指定された ContentType の値と同じであることを確認してください。 //Metadata: map[string]string{"key1": "value1", "key2": "value2"}, // URL に含まれる Metadata パラメーターの値が、リクエストで指定された Metadata の値と同じであることを確認してください。 }, oss.PresignExpires(10*time.Minute), ) if err != nil { log.Fatalf("failed to put object presign %v", err) } log.Printf("request method:%v\n", result.Method) log.Printf("request expiration:%v\n", result.Expiration) log.Printf("request url:%v\n", result.URL) if len(result.SignedHeaders) > 0 { // HTTP PUT リクエストを許可する署名付き URL を生成する際にリクエストヘッダーを指定する場合は、そのリクエストヘッダーが署名付き URL を使用して開始される PUT リクエストに含まれていることを確認してください。 log.Printf("signed headers:\n") for k, v := range result.SignedHeaders { log.Printf("%v: %v\n", k, v) } } }Python
SDK の詳細については、「Python で署名付き URL を使用してファイルをアップロード」をご参照ください。
import argparse import requests import alibabacloud_oss_v2 as oss from datetime import datetime, timedelta # コマンドラインパラメーターパーサーを作成し、スクリプトの目的を記述します。この例では、HTTP PUT リクエストを許可する署名付き URL を生成する方法を説明します。 parser = argparse.ArgumentParser(description="presign put object sample") # 必須のリージョン、バケット名、エンドポイント、オブジェクト名を含むコマンドラインパラメーターを指定します。 parser.add_argument('--region', help='The region in which the bucket is located.', required=True) parser.add_argument('--bucket', help='The name of the bucket.', required=True) parser.add_argument('--endpoint', help='The domain names that other services can use to access OSS') parser.add_argument('--key', help='The name of the object.', required=True) def main(): # コマンドラインパラメーターを解析して、ユーザーが指定した値を取得します。 args = parser.parse_args() # 認証のために環境変数からアクセス認証情報を取得します。 credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider() # SDK のデフォルト構成を使用して構成オブジェクトを作成し、認証情報プロバイダーを指定します。 cfg = oss.config.load_default() cfg.credentials_provider = credentials_provider # ユーザーが指定したコマンドラインパラメーターに基づいて、構成オブジェクトのリージョン属性を指定します。 cfg.region = args.region # カスタムエンドポイントが提供されている場合は、構成オブジェクトのエンドポイントパラメーターを変更します。 if args.endpoint is not None: cfg.endpoint = args.endpoint # 上記の構成を使用して OSSClient インスタンスを初期化し、インスタンスが OSS と対話できるようにします。 client = oss.Client(cfg) # PUT リクエストを開始し、指定されたオブジェクトの署名付き URL を生成するリクエストを送信します。 pre_result = client.presign(oss.PutObjectRequest( bucket=args.bucket, # バケットの名前。 key=args.key, # オブジェクトの名前。 ),expires=timedelta(seconds=3600)) # リクエストの有効期間を指定します。この例では、有効期間は 3,600 秒に設定されています。 # リクエストで指定されたメソッド、有効期限、署名付き URL を表示して、署名付き URL の有効性を確認します。 print(f'method: {pre_result.method},' f' expiration: {pre_result.expiration.strftime("%Y-%m-%dT%H:%M:%S.000Z")},' f' url: {pre_result.url}' ) # リクエストの署名付きヘッダーを表示します。これは、リクエストが送信されるときに HTTP ヘッダーに含まれます。 for key, value in pre_result.signed_headers.items(): print(f'signed headers key: {key}, signed headers value: {value}') # スクリプトが直接実行されるときに処理ロジックを開始するために main 関数を呼び出します。 if __name__ == "__main__": main() # スクリプトの関数のエントリポイントを指定します。制御フローはここから始まります。Node.js
このセクションでは、一般的なシナリオの例を示します。画像処理パラメーターまたはバージョン ID を持つ署名付き URL を生成する方法の詳細については、「Node.js で署名付き URL を使用してファイルをアップロード」をご参照ください。
const OSS = require("ali-oss"); // 署名付き URL を生成する関数を定義します。 async function generateSignatureUrl(fileName) { // 署名付き URL を取得します。 const client = await new OSS({ accessKeyId: 'yourAccessKeyId', accessKeySecret: 'yourAccessKeySecret', bucket: 'examplebucket', region: 'oss-cn-hangzhou', authorizationV4: true }); return await client.signatureUrlV4('PUT', 3600, { headers: {} // 実際のリクエストヘッダーに基づいてリクエストヘッダーを設定します。 }, fileName); } // 関数を呼び出し、ファイル名を渡します。 generateSignatureUrl('yourFileName').then(url => { console.log('Generated Signature URL:', url); }).catch(err => { console.error('Error generating signature URL:', err); });PHP
このセクションでは、一般的なシナリオの例を示します。バージョン ID を持つ署名付き URL を生成する方法の詳細については、「PHP で署名付き URL を使用してファイルをアップロード」をご参照ください。
<?php if (is_file(__DIR__ . '/../autoload.php')) { require_once __DIR__ . '/../autoload.php'; } if (is_file(__DIR__ . '/../vendor/autoload.php')) { require_once __DIR__ . '/../vendor/autoload.php'; } use OSS\OssClient; use OSS\Core\OssException; use OSS\Http\RequestCore; use OSS\Http\ResponseCore; use OSS\Credentials\EnvironmentVariableCredentialsProvider; // 環境変数からアクセス認証情報を取得します。サンプルコードを実行する前に、OSS_ACCESS_KEY_ID および OSS_ACCESS_KEY_SECRET 環境変数が設定されていることを確認してください。 $provider = new EnvironmentVariableCredentialsProvider(); // バケットが配置されているリージョンのエンドポイントを指定します。たとえば、バケットが中国 (杭州) リージョンにある場合、エンドポイントを https://oss-cn-hangzhou.aliyuncs.com に設定します。 $endpoint = "yourEndpoint"; // バケットの名前を指定します。 $bucket= "examplebucket"; // オブジェクトの完全なパスを指定します。オブジェクトの完全なパスにバケット名を含めないでください。 $object = "exampleobject.txt"; // 署名付き URL の有効期間を 600 秒に設定します。最大値: 32400。 $timeout = 600; try { $config = array( "provider" => $provider, "endpoint" => $endpoint, 'signatureVersion'=>OssClient::OSS_SIGNATURE_VERSION_V4, "region"=> "cn-hangzhou" ); $ossClient = new OssClient($config); // 署名付き URL を生成します。 $signedUrl = $ossClient->signUrl($bucket, $object, $timeout, "PUT"); print_r($signedUrl); } catch (OssException $e) { printf(__FUNCTION__ . ": FAILED\n"); printf($e->getMessage() . "\n"); return; }Android
SDK の詳細については、「Android で署名付き URL を使用してファイルをアップロード」をご参照ください。
// バケット名を指定します (例: examplebucket)。 String bucketName = "examplebucket"; // ソースオブジェクトの完全なパスを、バケット名なしで指定します (例: exampleobject.txt)。 String objectKey = "exampleobject.txt"; // content-type を設定します。 String contentType = "application/octet-stream"; String url = null; try { // ファイルをアップロードするための署名付き URL を生成します。 GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucketName, objectKey); // 署名付き URL の有効期限を 30 分に設定します。 request.setExpiration(30*60); request.setContentType(contentType); request.setMethod(HttpMethod.PUT); url = oss.presignConstrainedObjectURL(request); Log.d("url", url); } catch (ClientException e) { e.printStackTrace(); }C++
SDK の詳細については、「C++ で署名付き URL を使用してファイルをアップロード」をご参照ください。
#include <alibabacloud/oss/OssClient.h> using namespace AlibabaCloud::OSS; int main(void) { /* OSS へのアクセスに使用するアカウントに関する情報を初期化します。*/ /* バケットが配置されているリージョンのエンドポイントを指定します。たとえば、バケットが中国 (杭州) リージョンにある場合、エンドポイントを https://oss-cn-hangzhou.aliyuncs.com に設定します。*/ std::string Endpoint = "yourEndpoint"; /* バケットが配置されているリージョンを指定します。たとえば、バケットが中国 (杭州) リージョンにある場合、リージョンを cn-hangzhou に設定します。* / std::string Region = "yourRegion"; /* バケットの名前を指定します。例: examplebucket。*/ std::string BucketName = "examplebucket"; /* オブジェクトの完全なパスを指定します。完全なパスにバケット名を含めないでください。例: exampledir/exampleobject.txt。*/ std::string PutobjectUrlName = "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); /* 署名付き URL の有効期間を指定します。最大有効期間は 32,400 です。単位: 秒。*/ std::time_t t = std::time(nullptr) + 1200; /* 署名付き URL を生成します。*/ auto genOutcome = client.GeneratePresignedUrl(BucketName, PutobjectUrlName, t, Http::Put); if (genOutcome.isSuccess()) { std::cout << "GeneratePresignedUrl success, Gen url:" << genOutcome.result().c_str() << std::endl; } else { /* 例外を処理します。*/ std::cout << "GeneratePresignedUrl fail" << ",code:" << genOutcome.error().Code() << ",message:" << genOutcome.error().Message() << ",requestId:" << genOutcome.error().RequestId() << std::endl; return -1; } /* ネットワークリソースなどのリソースを解放します。*/ ShutdownSdk(); return 0; }iOS
SDK の詳細については、「iOS で署名付き URL を使用してファイルをアップロード」をご参照ください。
// バケットの名前を指定します。 NSString *bucketName = @"examplebucket"; // オブジェクトの名前を指定します。 NSString *objectKey = @"exampleobject.txt"; NSURL *file = [NSURL fileURLWithPath:@"<filePath>"]; NSString *contentType = [OSSUtil detemineMimeTypeForFilePath:file.absoluteString uploadName:objectKey]; __block NSString *urlString; // オブジェクトをアップロードするための有効期間付きの署名付き URL を生成します。この例では、URL の有効期間は 30 分です。 OSSTask *task = [client presignConstrainURLWithBucketName:bucketName withObjectKey:objectKey httpMethod:@"PUT" withExpirationInterval:30 * 60 withParameters:@{} contentType:contentType contentMd5:nil]; [task continueWithBlock:^id _Nullable(OSSTask * _Nonnull task) { if (task.error) { NSLog(@"presign error: %@", task.error); } else { urlString = task.result; NSLog(@"url: %@", urlString); } return nil; }];.NET
SDK の詳細については、「.NET で署名付き URL を使用してファイルをアップロード」をご参照ください。
using Aliyun.OSS; using Aliyun.OSS.Common; // バケットが配置されているリージョンのエンドポイントを指定します。たとえば、バケットが中国 (杭州) リージョンにある場合、エンドポイントを https://oss-cn-hangzhou.aliyuncs.com に設定します。 var endpoint = "https://oss-cn-hangzhou.aliyuncs.com"; // 環境変数からアクセス認証情報を取得します。このコードを実行する前に、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"; var objectContent = "More than just cloud."; // バケットが配置されているリージョンを指定します。たとえば、バケットが中国 (杭州) リージョンにある場合、リージョンを 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); try { // 署名付き URL を生成します。 var generatePresignedUriRequest = new GeneratePresignedUriRequest(bucketName, objectName, SignHttpMethod.Put) { // 署名付き URL の有効期限を設定します。デフォルト値は 3600 秒です。 Expiration = DateTime.Now.AddHours(1), }; var signedUrl = client.GeneratePresignedUri(generatePresignedUriRequest); } catch (OssException ex) { Console.WriteLine("Failed with error code: {0}; Error info: {1}. \nRequestID:{2}\tHostID:{3}", ex.ErrorCode, ex.Message, ex.RequestId, ex.HostId); } catch (Exception ex) { Console.WriteLine("Failed with error info: {0}", ex.Message); }C
SDK の詳細については、「C で署名付き URL を使用してファイルをダウンロード」をご参照ください。
#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 *local_filename = "yourLocalFilename"; 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")); /* CNAME を使用して OSS にアクセスするかどうかを指定します。値 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); } /* メモリ管理用のメモリプール (pool)。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_string_t file; aos_http_request_t *req; apr_time_t now; char *url_str; aos_string_t url; int64_t expire_time; int one_hour = 3600; aos_str_set(&bucket, bucket_name); aos_str_set(&object, object_name); aos_str_set(&file, local_filename); expire_time = now / 1000000 + one_hour; req = aos_http_request_create(pool); req->method = HTTP_PUT; now = apr_time_now(); /* 単位: マイクロ秒。*/ expire_time = now / 1000000 + one_hour; /* 署名付き URL を生成します。*/ url_str = oss_gen_signed_url(oss_client_options, &bucket, &object, expire_time, req); aos_str_set(&url, url_str); printf("Temporary upload URL: %s\n", url_str); /* メモリプールを解放します。これは、リクエスト中にさまざまなリソースに割り当てられたメモリを解放することと同じです。*/ aos_pool_destroy(pool); /* 以前に割り当てられたグローバルリソースを解放します。*/ aos_http_io_deinitialize(); return 0; }
サードパーティが生成された署名付き URL を使用して、PUT リクエストでファイルをアップロードします。
重要署名付き URL は、有効期限が切れる前に複数回アクセスできます。ただし、複数のアップロード操作を実行すると、ファイルが上書きされるリスクがあります。URL の有効期限が切れた後、ファイルへのアクセスを継続するには、ステップ 1 に従って署名付き URL を再生成する必要があります。
curl
curl -X PUT -T /path/to/local/file "https://exampleobject.oss-cn-hangzhou.aliyuncs.com/exampleobject.txt?x-oss-date=20241112T083238Z&x-oss-expires=3599&x-oss-signature-version=OSS4-HMAC-SHA256&x-oss-credential=LTAI****************%2F20241112%2Fcn-hangzhou%2Foss%2Faliyun_v4_request&x-oss-signature=ed5a******************************************************"Java
import org.apache.http.HttpEntity; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpPut; import org.apache.http.entity.FileEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import java.io.*; import java.net.URL; import java.util.*; public class SignUrlUpload { public static void main(String[] args) throws Throwable { CloseableHttpClient httpClient = null; CloseableHttpResponse response = null; // <signedUrl> を承認済み URL に置き換えます。 URL signedUrl = new URL("<signedUrl>"); // ローカルファイルの完全なパスを指定します。ローカルパスを指定しない場合、ファイルはサンプルプログラムのプロジェクトパスからデフォルトでアップロードされます。 String pathName = "C:\\Users\\demo.txt"; try { HttpPut put = new HttpPut(signedUrl.toString()); System.out.println(put); HttpEntity entity = new FileEntity(new File(pathName)); put.setEntity(entity); httpClient = HttpClients.createDefault(); response = httpClient.execute(put); System.out.println("Status code returned for the upload:"+response.getStatusLine().getStatusCode()); if(response.getStatusLine().getStatusCode() == 200){ System.out.println("Upload successful using network library."); } System.out.println(response.toString()); } catch (Exception e){ e.printStackTrace(); } finally { response.close(); httpClient.close(); } } }Go
package main import ( "fmt" "io" "net/http" "os" ) func uploadFile(signedUrl, filePath string) error { // ファイルを開きます。 file, err := os.Open(filePath) if err != nil { return fmt.Errorf("Unable to open file: %w", err) } defer file.Close() // 新しい HTTP クライアントを作成します。 client := &http.Client{} // PUT リクエストを作成します。 req, err := http.NewRequest("PUT", signedUrl, file) if err != nil { return fmt.Errorf("Failed to create request: %w", err) } // リクエストを送信します。 resp, err := client.Do(req) if err != nil { return fmt.Errorf("Failed to send request: %w", err) } defer resp.Body.Close() // 応答を読み取ります。 body, err := io.ReadAll(resp.Body) if err != nil { return fmt.Errorf("Failed to read response: %w", err) } fmt.Printf("Status code returned for the upload: %d\n", resp.StatusCode) if resp.StatusCode == 200 { fmt.Println("Upload successful using network library.") } fmt.Println(string(body)) return nil } func main() { // <signedUrl> を承認済み URL に置き換えます。 signedUrl := "<signedUrl>" // ローカルファイルの完全なパスを指定します。ローカルパスを指定しない場合、ファイルはサンプルプログラムのプロジェクトパスからデフォルトでアップロードされます。 filePath := "C:\\Users\\demo.txt" err := uploadFile(signedUrl, filePath) if err != nil { fmt.Println("An error occurred:", err) } }python
import requests def upload_file(signed_url, file_path): try: # ファイルを開きます。 with open(file_path, 'rb') as file: # PUT リクエストを送信してファイルをアップロードします。 response = requests.put(signed_url, data=file) print(f"Status code returned for the upload: {response.status_code}") if response.status_code == 200: print("Upload successful using network library.") print(response.text) except Exception as e: print(f"An error occurred: {e}") if __name__ == "__main__": # <signedUrl> を承認済み URL に置き換えます。 signed_url = "<signedUrl>" // ローカルファイルの完全なパスを指定します。ローカルパスを指定しない場合、ファイルはサンプルプログラムのプロジェクトパスからデフォルトでアップロードされます。 file_path = "C:\\Users\\demo.txt" upload_file(signed_url, file_path)Node.js
const fs = require('fs'); const axios = require('axios'); async function uploadFile(signedUrl, filePath) { try { // 読み取りストリームを作成します。 const fileStream = fs.createReadStream(filePath); // PUT リクエストを送信してファイルをアップロードします。 const response = await axios.put(signedUrl, fileStream, { headers: { 'Content-Type': 'application/octet-stream' // 必要に応じて Content-Type を調整します。 } }); console.log(`Status code returned for the upload: ${response.status}`); if (response.status === 200) { console.log('Upload successful using network library.'); } console.log(response.data); } catch (error) { console.error(`An error occurred: ${error.message}`); } } // メイン関数。 (async () => { // <signedUrl> を承認済み URL に置き換えます。 const signedUrl = '<signedUrl>'; // ローカルファイルの完全なパスを指定します。ローカルパスを指定しない場合、ファイルはサンプルプログラムのプロジェクトパスからデフォルトでアップロードされます。 const filePath = 'C:\\Users\\demo.txt'; await uploadFile(signedUrl, filePath); })();browser.js
重要Browser.js を使用してファイルをアップロードする際に 403 署名不一致エラーが発生した場合、通常はブラウザが自動的に Content-Type リクエストヘッダーを追加するものの、署名付き URL の生成時にこのヘッダーが指定されていなかったことが原因です。これにより、署名検証が失敗します。この問題を解決するには、署名付き URL を生成する際に Content-Type リクエストヘッダーを指定する必要があります。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>File Upload Example</title> </head> <body> <h1>File Upload Example</h1> <!-- ファイルを選択 --> <input type="file" id="fileInput" /> <button id="uploadButton">Upload File</button> <script> // これをステップ 1 で生成された署名付き URL に置き換えます。 const signedUrl = "<signedUrl>"; document.getElementById('uploadButton').addEventListener('click', async () => { const fileInput = document.getElementById('fileInput'); const file = fileInput.files[0]; if (!file) { alert('Please select a file to upload.'); return; } try { await upload(file, signedUrl); alert('File uploaded successfully!'); } catch (error) { console.error('Error during upload:', error); alert('Upload failed: ' + error.message); } }); /** * ファイルを OSS にアップロードします。 * @param {File} file - アップロードするファイル。 * @param {string} presignedUrl - 署名付き URL。 */ const upload = async (file, presignedUrl) => { const response = await fetch(presignedUrl, { method: 'PUT', body: file, // ファイル全体を直接アップロードします。 }); if (!response.ok) { throw new Error(`Upload failed, status: ${response.status}`); } console.log('File uploaded successfully'); }; </script> </body> </html>C#
using System.Net.Http.Headers; // ローカルファイルの完全なパスを指定します。ローカルパスを指定しない場合、ファイルはサンプルプログラムのプロジェクトパスからデフォルトでアップロードされます。 var filePath = "C:\\Users\\demo.txt"; // <signedUrl> を承認済み URL に置き換えます。 var presignedUrl = "<signedUrl>"; // HTTP クライアントを作成し、ローカルファイルストリームを開きます。 using var httpClient = new HttpClient(); using var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read); using var content = new StreamContent(fileStream); // PUT リクエストを作成します。 var request = new HttpRequestMessage(HttpMethod.Put, presignedUrl); request.Content = content; // リクエストを送信します。 var response = await httpClient.SendAsync(request); // 応答を処理します。 if (response.IsSuccessStatusCode) { Console.WriteLine($"Upload successful! Status code: {response.StatusCode}"); Console.WriteLine("Response headers:"); foreach (var header in response.Headers) { Console.WriteLine($"{header.Key}: {string.Join(", ", header.Value)}"); } } else { string responseContent = await response.Content.ReadAsStringAsync(); Console.WriteLine($"Upload failed! Status code: {response.StatusCode}"); Console.WriteLine("Response content: " + responseContent); }C++
#include <iostream> #include <fstream> #include <curl/curl.h> void uploadFile(const std::string& signedUrl, const std::string& filePath) { CURL *curl; CURLcode res; curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); if (curl) { // URL を設定します。 curl_easy_setopt(curl, CURLOPT_URL, signedUrl.c_str()); // リクエストメソッドを PUT に設定します。 curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); // ファイルを開きます。 FILE *file = fopen(filePath.c_str(), "rb"); if (!file) { std::cerr << "Unable to open file: " << filePath << std::endl; return; } // ファイルサイズを取得します。 fseek(file, 0, SEEK_END); long fileSize = ftell(file); fseek(file, 0, SEEK_SET); // ファイルサイズを設定します。 curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)fileSize); // 入力ファイルハンドルを設定します。 curl_easy_setopt(curl, CURLOPT_READDATA, file); // リクエストを実行します。 res = curl_easy_perform(curl); if (res != CURLE_OK) { std::cerr << "curl_easy_perform() failed: " << curl_easy_strerror(res) << std::endl; } else { long httpCode = 0; curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode); std::cout << "Status code returned for the upload: " << httpCode << std::endl; if (httpCode == 200) { std::cout << "Upload successful using network library." << std::endl; } } // ファイルを閉じます。 fclose(file); // クリーンアップします。 curl_easy_cleanup(curl); } curl_global_cleanup(); } int main() { // <signedUrl> を承認済み URL に置き換えます。 std::string signedUrl = "<signedUrl>"; // ローカルファイルの完全なパスを指定します。ローカルパスを指定しない場合、ファイルはサンプルプログラムのプロジェクトパスからデフォルトでアップロードされます。 std::string filePath = "C:\\Users\\demo.txt"; uploadFile(signedUrl, filePath); return 0; }Android
package com.example.signurlupload; import android.os.AsyncTask; import android.util.Log; import java.io.DataOutputStream; import java.io.FileInputStream; import java.io.IOException; import java.net.HttpURLConnection; import java.net.URL; public class SignUrlUploadActivity { private static final String TAG = "SignUrlUploadActivity"; public void uploadFile(String signedUrl, String filePath) { new UploadTask().execute(signedUrl, filePath); } private class UploadTask extends AsyncTask<String, Void, String> { @Override protected String doInBackground(String... params) { String signedUrl = params[0]; String filePath = params[1]; HttpURLConnection connection = null; DataOutputStream dos = null; FileInputStream fis = null; try { URL url = new URL(signedUrl); connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("PUT"); connection.setDoOutput(true); connection.setRequestProperty("Content-Type", "application/octet-stream"); fis = new FileInputStream(filePath); dos = new DataOutputStream(connection.getOutputStream()); byte[] buffer = new byte[1024]; int length; while ((length = fis.read(buffer)) != -1) { dos.write(buffer, 0, length); } dos.flush(); dos.close(); fis.close(); int responseCode = connection.getResponseCode(); Log.d(TAG, "Status code returned for the upload: " + responseCode); if (responseCode == 200) { Log.d(TAG, "Upload successful using network library."); } return "Upload complete. Status code: " + responseCode; } catch (IOException e) { e.printStackTrace(); return "Upload failed: " + e.getMessage(); } finally { if (connection != null) { connection.disconnect(); } } } @Override protected void onPostExecute(String result) { Log.d(TAG, result); } } public static void main(String[] args) { SignUrlUploadActivity activity = new SignUrlUploadActivity(); // <signedUrl> を承認済み URL に置き換えます。 String signedUrl = "<signedUrl>"; // ローカルファイルの完全なパスを指定します。ローカルパスを指定しない場合、ファイルはサンプルプログラムのプロジェクトパスからデフォルトでアップロードされます。 String filePath = "C:\\Users\\demo.txt"; activity.uploadFile(signedUrl, filePath); } }
署名付き URL を使用したマルチパートアップロードの実行
クライアントを OSS SDK と統合できないが、大きなファイルをアップロードする必要がある場合は、署名付き URL を使用してマルチパートアップロードを実行できます。この方法では、サーバーがアップロードタスクを開始し、各パートの権限を持つ署名付き URL を生成します。その後、クライアントまたはサードパーティのアプリケーションがこれらの URL を使用してパートをアップロードします。すべてのパートがアップロードされた後、サーバーはパートを完全なファイルにマージするリクエストを開始します。
署名付き URL を使用したマルチパートアップロードは比較的複雑です。クライアントは、URL で指定された `partNumber` に対応する正しいパートをアップロードする必要があります。パートが欠落していたり、不一致があったりすると、最終的なファイルが正しくなくなります。したがって、クライアントを OSS SDK と統合できる場合は、STS 権限付与を使用してクライアントサイドの直接アップロードを実装することを推奨します。この方法は開発がより簡単で、より安定したアップロードを提供します。
クライアントがアップロードリクエストを開始
クライアントは、ファイル名、ファイルサイズ、および希望するパートサイズを含むアップロードリクエストをサーバーに送信します。パートサイズは 5 GB を超えることはできません。パートサイズは 5 MB を推奨します。
次の例はリクエストを示しています。この例では、
https://yourserver.com/init-uploadはサーバーが提供する初期化 API エンドポイントです。実際のエンドポイントに置き換えてください。curl -X POST https://yourserver.com/init-upload \ -H "Content-Type: application/json" \ -d '{ "fileName": "exampleobject.jpg", "fileSize": 104857600, "partSize": 5242880 }'サーバーがアップロードタスクを開始し、署名付き URL を生成
InitiateMultipartUpload 操作を呼び出してアップロードタスクを初期化し、UploadId を取得します。
ファイルサイズと希望するパートサイズに基づいてパートの数を計算します。
各パートに対応する署名付き URL を生成します。
URL のリストを JSON 形式で返します。
説明サーバーは UploadId を記録し、アップロードされたファイルとの一意のマッピングを確保する必要があります。これは、後続のパートの検証とマージに必要です。必要に応じて、キャッシュまたはデータベースを使用して UploadId を保存できます。
クライアントがパートデータをアップロード
クライアントは、サーバーから返された署名付き URL のリストを使用して、HTTP PUT リクエストで各パートをアップロードします。この方法は、単一ファイルのアップロードと同じです。すべてのパートがアップロードされた後、クライアントはサーバーにマージ操作を開始するよう通知する必要があります。
説明同時アップロードがサポートされています。ただし、各 URL を使用してアップロードされるコンテンツが正しいパートに対応していることを確認する必要があります。つまり、`partNumber=N` の URL では、ファイルの N 番目のパートのみをアップロードできます。パートを混在させたり、スキップしたりすることはできません。
次の例は、最初のパートをアップロードする方法を示しています。/path/to/local/file はローカルパートのパスです。
curl -X PUT -T /path/to/local/file "https://examplebucket.oss-cn-hangzhou.aliyuncs.com/exampleobject.jpg?partNumber=1&uploadId=BE2D0BC931BE4DE1B23F339AABFA49EE&x-oss-credential=LTAI********************%2F20250520%2Fcn-hangzhou%2Foss%2Faliyun_v4_request&x-oss-date=20250520T082728Z&x-oss-expires=3600&x-oss-signature=81f3d2e5eaa67c432291577ed20af3b3f60df05ab3cddedcdce168ef707f7ad0&x-oss-signature-version=OSS4-HMAC-SHA256"(オプション) サーバーがアップロードされたパートを検証
サーバーが「アップロード完了」通知を受け取った後、ListParts 操作を呼び出して以下を検証できます。
パートの数が完全であるかどうか。
各パートのサイズが期待どおりであるかどうか。
説明この操作では、以前に記録された UploadId を使用します。
サーバーがパートをマージし、結果を返す
検証が成功した後、サーバーは CompleteMultipartUpload 操作を呼び出してパートをマージし、アップロード結果をクライアントに返します。
アップロードポリシーを定義するためのヘッダーの設定
署名付き URL を生成する際に、ヘッダーパラメーターを指定してアップロードポリシーを定義できます。たとえば、次のコード例に示すように、ファイルのストレージクラス x-oss-storage-class とコンテンツタイプ Content-Type を設定できます。
署名付き URL の生成時にヘッダーパラメーターを指定した場合、署名付き URL を使用してファイルをアップロードする際にも同じヘッダーを渡す必要があります。そうしないと、署名検証が失敗するため、OSS は 403 エラーを返します。
設定可能な OSS システムヘッダーの詳細については、「PutObject」をご参照ください。また、カスタムヘッダーを設定してファイルを管理することもできます。詳細については、「ファイルメタデータの管理」をご参照ください。
バケットのオーナーがヘッダーパラメーター付きの署名付き URL を生成します。
Java
import com.aliyun.oss.*; import com.aliyun.oss.common.auth.*; import com.aliyun.oss.common.comm.SignVersion; import com.aliyun.oss.internal.OSSHeaders; import com.aliyun.oss.model.GeneratePresignedUrlRequest; import com.aliyun.oss.model.StorageClass; import java.net.URL; import java.util.*; import java.util.Date; public class GetSignUrl { public static void main(String[] args) throws Throwable { // この例では、中国 (杭州) リージョンのパブリックエンドポイントを使用します。実際のエンドポイントを指定してください。 String endpoint = "https://oss-cn-hangzhou.aliyuncs.com"; // 環境変数からアクセス認証情報を取得します。サンプルコードを実行する前に、OSS_ACCESS_KEY_ID および OSS_ACCESS_KEY_SECRET 環境変数が設定されていることを確認してください。 EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider(); // バケット名を指定します (例: examplebucket)。 String bucketName = "examplebucket"; // オブジェクトの完全なパスを指定します (例: exampleobject.txt)。オブジェクトの完全なパスにバケット名を含めることはできません。 String objectName = "exampleobject.txt"; // バケットが配置されているリージョンを指定します。たとえば、バケットが中国 (杭州) リージョンにある場合、リージョンを 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(); // リクエストヘッダーを設定します。 Map<String, String> headers = new HashMap<String, String>(); // StorageClass を指定します。 headers.put(OSSHeaders.STORAGE_CLASS, StorageClass.Standard.toString()); // ContentType を指定します。 headers.put(OSSHeaders.CONTENT_TYPE, "text/plain; charset=utf8"); // カスタムユーザーメタデータを設定します。 Map<String, String> userMetadata = new HashMap<String, String>(); userMetadata.put("key1","value1"); userMetadata.put("key2","value2"); URL signedUrl = null; try { // 生成された署名付き URL の有効期限をミリ秒単位で指定します。この例では、有効期限を 1 時間に設定します。 Date expiration = new Date(new Date().getTime() + 3600 * 1000L); // 署名付き URL を生成します。 GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucketName, objectName, HttpMethod.PUT); // 有効期限を設定します。 request.setExpiration(expiration); // リクエストにリクエストヘッダーを追加します。 request.setHeaders(headers); // カスタムユーザーメタデータを追加します。 request.setUserMetadata(userMetadata); // HTTP PUT リクエスト用の署名付き URL を生成します。 signedUrl = ossClient.generatePresignedUrl(request); // 署名付き URL を出力します。 System.out.println("signed url for putObject: " + signedUrl); } 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()); } } }Go
package main import ( "context" "flag" "log" "time" "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() // バケットの名前が指定されているかどうかを確認します。 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) // PutObject リクエスト用の署名付き URL を生成します。 result, err := client.Presign(context.TODO(), &oss.PutObjectRequest{ Bucket: oss.Ptr(bucketName), Key: oss.Ptr(objectName), ContentType: oss.Ptr("text/plain;charset=utf8"), // URL に含まれる ContentType パラメーターの値が、リクエストで指定された ContentType の値と同じであることを確認してください。 StorageClass: oss.StorageClassStandard, // URL に含まれる StorageClass パラメーターの値が、リクエストで指定された StorageClass の値と同じであることを確認してください。 Metadata: map[string]string{"key1": "value1", "key2": "value2"}, // URL に含まれる Metadata の値が、リクエストで指定された Metadata の値と同じであることを確認してください。 }, oss.PresignExpires(10*time.Minute), ) if err != nil { log.Fatalf("failed to put object presign %v", err) } log.Printf("request method:%v\n", result.Method) log.Printf("request expiration:%v\n", result.Expiration) log.Printf("request url:%v\n", result.URL) if len(result.SignedHeaders) > 0 { // HTTP PUT リクエストを許可する署名付き URL を生成する際にリクエストヘッダーを指定する場合は、そのリクエストヘッダーが URL を使用して開始される PUT リクエストに含まれていることを確認してください。 log.Printf("signed headers:\n") for k, v := range result.SignedHeaders { log.Printf("%v: %v\n", k, v) } } }Python
import argparse import requests import alibabacloud_oss_v2 as oss from datetime import datetime, timedelta # コマンドラインパラメーターパーサーを作成し、スクリプトの目的を記述します。この例では、HTTP PUT リクエストを許可する署名付き URL を生成する方法を説明します。 parser = argparse.ArgumentParser(description="presign put object sample") # 必須のリージョン、バケット名、エンドポイント、オブジェクト名を含むコマンドラインパラメーターを指定します。 parser.add_argument('--region', help='The region in which the bucket is located.', required=True) parser.add_argument('--bucket', help='The name of the bucket.', required=True) parser.add_argument('--endpoint', help='The domain names that other services can use to access OSS') parser.add_argument('--key', help='The name of the object.', required=True) def main(): # コマンドラインパラメーターを解析して、ユーザーが指定した値を取得します。 args = parser.parse_args() # 認証のために環境変数からアクセス認証情報を取得します。 credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider() # SDK のデフォルト構成を使用して構成オブジェクトを作成し、認証情報プロバイダーを指定します。 cfg = oss.config.load_default() cfg.credentials_provider = credentials_provider # ユーザーが指定したコマンドラインパラメーターに基づいて、構成オブジェクトのリージョン属性を指定します。 cfg.region = args.region # カスタムエンドポイントが提供されている場合は、構成オブジェクトのエンドポイントパラメーターを変更します。 if args.endpoint is not None: cfg.endpoint = args.endpoint # 上記の構成を使用して OSSClient インスタンスを初期化し、インスタンスが OSS と対話できるようにします。 client = oss.Client(cfg) # PUT リクエストを開始し、指定されたオブジェクトの署名付き URL を生成するリクエストを送信します。 pre_result = client.presign(oss.PutObjectRequest( bucket=args.bucket, # バケットの名前。 key=args.key, # オブジェクトの名前。 content_type='text/plain;charset=utf8', # オブジェクトのタイプを指定します。 storage_class='Standard', # オブジェクトのストレージクラスを指定します。 metadata={ 'key1': 'value1', # オブジェクトのメタデータを指定します。 'key2': 'value2' # オブジェクトのメタデータを指定します。 } ),expires=timedelta(seconds=3600)) # リクエストの有効期間を指定します。この例では、有効期間は 3,600 秒に設定されています。 # リクエストで指定されたメソッド、有効期限、署名付き URL を表示して、署名付き URL の有効性を確認します。 print(f'method: {pre_result.method},' f' expiration: {pre_result.expiration.strftime("%Y-%m-%dT%H:%M:%S.000Z")},' f' url: {pre_result.url}' ) # リクエストの署名付きヘッダーを表示します。これは、リクエストが送信されるときに HTTP ヘッダーに含まれます。 for key, value in pre_result.signed_headers.items(): print(f'signed headers key: {key}, signed headers value: {value}') # スクリプトが直接実行されるときに処理ロジックを開始するために main 関数を呼び出します。 if __name__ == "__main__": main() # スクリプトの関数のエントリポイントを指定します。制御フローはここから始まります。サードパーティが署名付き URL を使用してファイルをアップロードし、同じヘッダーを渡します。
curl
curl -X PUT \ -H "Content-Type: text/plain;charset=utf8" \ -H "x-oss-storage-class: Standard" \ -H "x-oss-meta-key1: value1" \ -H "x-oss-meta-key2: value2" \ -T "C:\\Users\\demo.txt" \ "https://exampleobject.oss-cn-hangzhou.aliyuncs.com/exampleobject.txt?x-oss-date=20241112T083238Z&x-oss-expires=3599&x-oss-signature-version=OSS4-HMAC-SHA256&x-oss-credential=LTAI****************%2F20241112%2Fcn-hangzhou%2Foss%2Faliyun_v4_request&x-oss-signature=ed5a******************************************************"Java
import com.aliyun.oss.internal.OSSHeaders; import com.aliyun.oss.model.StorageClass; import org.apache.http.HttpEntity; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpPut; import org.apache.http.entity.FileEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import java.io.*; import java.net.URL; import java.util.*; public class SignUrlUpload { public static void main(String[] args) throws Throwable { CloseableHttpClient httpClient = null; CloseableHttpResponse response = null; // <signedUrl> を承認済み URL に置き換えます。 URL signedUrl = new URL("<signedUrl>"); // ローカルファイルの完全なパスを指定します。ローカルパスを指定しない場合、ファイルはサンプルプログラムのプロジェクトパスからデフォルトでアップロードされます。 String pathName = "C:\\Users\\demo.txt"; // リクエストヘッダーを設定します。リクエストヘッダー情報は、URL が生成されたときに使用された情報と同じでなければなりません。 Map<String, String> headers = new HashMap<String, String>(); //オブジェクトのストレージクラスを指定します。 headers.put(OSSHeaders.STORAGE_CLASS, StorageClass.Standard.toString()); //ContentType を指定します。 headers.put(OSSHeaders.CONTENT_TYPE, "text/plain;charset=utf8"); // カスタムユーザーメタデータを設定します。カスタムユーザーメタデータは、URL が生成されたときに使用された情報と同じでなければなりません。 Map<String, String> userMetadata = new HashMap<String, String>(); userMetadata.put("key1","value1"); userMetadata.put("key2","value2"); try { HttpPut put = new HttpPut(signedUrl.toString()); System.out.println(put); HttpEntity entity = new FileEntity(new File(pathName)); put.setEntity(entity); // 署名付き URL を生成する際にユーザーメタデータやストレージクラスなどのヘッダーパラメーターを設定した場合、署名付き URL を使用してファイルをアップロードする際にもこれらのパラメーターをサーバーに送信する必要があります。サーバーに送信されたパラメーターが署名付きパラメーターと一致しない場合、署名エラーが報告されます。 for(Map.Entry header: headers.entrySet()){ put.addHeader(header.getKey().toString(),header.getValue().toString()); } for(Map.Entry meta: userMetadata.entrySet()){ // userMeta を使用する場合、SDK は内部的に 'x-oss-meta-' プレフィックスを追加します。他の方法でアップロード用の署名付き URL を生成する場合も、userMeta に 'x-oss-meta-' プレフィックスを追加する必要があります。 put.addHeader("x-oss-meta-"+meta.getKey().toString(), meta.getValue().toString()); } httpClient = HttpClients.createDefault(); response = httpClient.execute(put); System.out.println("Status code returned for the upload:"+response.getStatusLine().getStatusCode()); if(response.getStatusLine().getStatusCode() == 200){ System.out.println("Upload successful using network library."); } System.out.println(response.toString()); } catch (Exception e){ e.printStackTrace(); } finally { response.close(); httpClient.close(); } } }Go
package main import ( "bytes" "fmt" "io/ioutil" "net/http" "os" ) func uploadFile(signedUrl string, filePath string, headers map[string]string, metadata map[string]string) error { // ファイルを開きます。 file, err := os.Open(filePath) if err != nil { return err } defer file.Close() // ファイルの内容を読み取ります。 fileBytes, err := ioutil.ReadAll(file) if err != nil { return err } // リクエストを作成します。 req, err := http.NewRequest("PUT", signedUrl, bytes.NewBuffer(fileBytes)) if err != nil { return err } // リクエストヘッダーを設定します。 for key, value := range headers { req.Header.Set(key, value) } // カスタムユーザーメタデータを設定します。 for key, value := range metadata { req.Header.Set(fmt.Sprintf("x-oss-meta-%s", key), value) } // リクエストを送信します。 client := &http.Client{} resp, err := client.Do(req) if err != nil { return err } defer resp.Body.Close() // 応答を処理します。 fmt.Printf("Status code returned for the upload: %d\n", resp.StatusCode) if resp.StatusCode == 200 { fmt.Println("Upload successful using network library.") } else { fmt.Println("Upload failed.") } body, _ := ioutil.ReadAll(resp.Body) fmt.Println(string(body)) return nil } func main() { // <signedUrl> を承認済み URL に置き換えます。 signedUrl := "<signedUrl>" // ローカルファイルの完全なパスを指定します。ローカルパスを指定しない場合、ファイルはサンプルプログラムのプロジェクトパスからデフォルトでアップロードされます。 filePath := "C:\\Users\\demo.txt" // リクエストヘッダーを設定します。リクエストヘッダー情報は、URL が生成されたときに使用された情報と同じでなければなりません。 headers := map[string]string{ "Content-Type": "text/plain;charset=utf8", "x-oss-storage-class": "Standard", } // カスタムユーザーメタデータを設定します。カスタムユーザーメタデータは、URL が生成されたときに使用された情報と同じでなければなりません。 metadata := map[string]string{ "key1": "value1", "key2": "value2", } err := uploadFile(signedUrl, filePath, headers, metadata) if err != nil { fmt.Printf("An error occurred: %v\n", err) } }Python
import requests from requests.auth import HTTPBasicAuth import os def upload_file(signed_url, file_path, headers=None, metadata=None): """ 署名付き URL を使用してファイルを OSS にアップロードします。 :param signed_url: 署名付き URL。 :param file_path: アップロードするファイルの完全なパス。 :param headers: オプション。カスタム HTTP ヘッダー。 :param metadata: オプション。カスタムメタデータ。 :return: None """ if not headers: headers = {} if not metadata: metadata = {} # ヘッダーを更新し、メタデータプレフィックスを追加します。 for key, value in metadata.items(): headers[f'x-oss-meta-{key}'] = value try: with open(file_path, 'rb') as file: response = requests.put(signed_url, data=file, headers=headers) print(f"Status code returned for the upload: {response.status_code}") if response.status_code == 200: print("Upload successful using network library.") else: print("Upload failed.") print(response.text) except Exception as e: print(f"An error occurred: {e}") if __name__ == "__main__": // <signedUrl> を承認済み URL に置き換えます。 signed_url = "<signedUrl>" // ローカルファイルの完全なパスを指定します。指定しない場合、ファイルはデフォルトでスクリプトが配置されているディレクトリからアップロードされます。 file_path = "C:\\Users\\demo.txt" // リクエストヘッダーを設定します。リクエストヘッダー情報は、URL が生成されたときに使用された情報と同じでなければなりません。 headers = { "Content-Type": "text/plain;charset=utf8", "x-oss-storage-class": "Standard" } // カスタムユーザーメタデータを設定します。カスタムユーザーメタデータは、URL が生成されたときに使用された情報と同じでなければなりません。 metadata = { "key1": "value1", "key2": "value2" } upload_file(signed_url, file_path, headers, metadata)Node.js
const fs = require('fs'); const axios = require('axios'); async function uploadFile(signedUrl, filePath, headers = {}, metadata = {}) { try { // ヘッダーを更新し、メタデータプレフィックスを追加します。 for (const [key, value] of Object.entries(metadata)) { headers[`x-oss-meta-${key}`] = value; } // ファイルストリームを読み取ります。 const fileStream = fs.createReadStream(filePath); // PUT リクエストを送信します。 const response = await axios.put(signedUrl, fileStream, { headers: headers }); console.log(`Status code returned for the upload: ${response.status}`); if (response.status === 200) { console.log("Upload successful using network library."); } else { console.log("Upload failed."); } console.log(response.data); } catch (error) { console.error(`An error occurred: ${error.message}`); } } // メイン関数。 (async () => { // <signedUrl> を承認済み URL に置き換えます。 const signedUrl = "<signedUrl>"; // ローカルファイルの完全なパスを指定します。指定しない場合、ファイルはデフォルトでスクリプトが配置されているディレクトリからアップロードされます。 const filePath = "C:\\Users\\demo.txt"; // リクエストヘッダーを設定します。リクエストヘッダー情報は、URL が生成されたときに使用された情報と同じでなければなりません。 const headers = { "Content-Type": "text/plain;charset=utf8", "x-oss-storage-class": "Standard" }; // カスタムユーザーメタデータを設定します。カスタムユーザーメタデータは、URL が生成されたときに使用された情報と同じでなければなりません。 const metadata = { "key1": "value1", "key2": "value2" }; await uploadFile(signedUrl, filePath, headers, metadata); })();Browser.js
重要Browser.js を使用してファイルをアップロードする際に 403 署名不一致エラーが発生した場合、通常はブラウザが自動的に Content-Type リクエストヘッダーを追加するものの、署名付き URL の生成時にこのヘッダーが指定されていなかったことが原因です。これにより、署名検証が失敗します。この問題を解決するには、署名付き URL を生成する際に Content-Type リクエストヘッダーを指定する必要があります。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>File Upload Example</title> </head> <body> <h1>File Upload Example (Java SDK)</h1> <input type="file" id="fileInput" /> <button id="uploadButton">Upload File</button> <script> // これを実際の署名付き URL に置き換えます。 const signedUrl = "<signedUrl>"; document.getElementById('uploadButton').addEventListener('click', async () => { const fileInput = document.getElementById('fileInput'); const file = fileInput.files[0]; if (file) { try { await upload(file, signedUrl); } catch (error) { console.error('Error during upload:', error); alert('Upload failed: ' + error.message); } } else { alert('Please select a file to upload.'); } }); const upload = async (file, presignedUrl) => { const headers = { "Content-Type": "text/plain;charset=utf8", 'x-oss-storage-class': 'Standard', 'x-oss-meta-key1': 'value1', 'x-oss-meta-key2': 'value2' }; const response = await fetch(presignedUrl, { method: 'PUT', headers: headers, body: file }); if (!response.ok) { throw new Error(`Upload failed, status: ${response.status}`); } alert('File uploaded successfully'); console.log('File uploaded successfully'); }; </script> </body> </html>C#
using System.Net.Http.Headers; // ローカルファイルの完全なパスを指定します。ローカルパスを指定しない場合、ファイルはサンプルプログラムのプロジェクトパスからデフォルトでアップロードされます。 var filePath = "C:\\Users\\demo.txt"; // <signedUrl> を承認済み URL に置き換えます。 var presignedUrl = "<signedUrl>"; // HTTP クライアントを作成し、ローカルファイルストリームを開きます。 using var httpClient = new HttpClient(); using var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read); using var content = new StreamContent(fileStream); // PUT リクエストを作成します。 var request = new HttpRequestMessage(HttpMethod.Put, presignedUrl); request.Content = content; // 署名付き URL を生成する際にユーザーメタデータやストレージクラスなどのヘッダーパラメーターを設定した場合、署名付き URL を使用してファイルをアップロードする際にもこれらのパラメーターをサーバーに送信する必要があります。サーバーに送信されたパラメーターが署名付きパラメーターと一致しない場合、署名エラーが報告されます。 // リクエストヘッダーを設定します。リクエストヘッダー情報は、URL が生成されたときに使用された情報と同じでなければなりません。 request.Content.Headers.ContentType = new MediaTypeHeaderValue("text/plain") { CharSet = "utf8" }; // ContentType を指定します。 // カスタムユーザーメタデータを設定します。カスタムユーザーメタデータは、URL が生成されたときに使用された情報と同じでなければなりません。 request.Content.Headers.Add("x-oss-meta-key1", "value1"); request.Content.Headers.Add("x-oss-meta-key2", "value2"); // オブジェクトのストレージクラスを指定します。 request.Content.Headers.Add("x-oss-storage-class", "Standard"); // リクエストヘッダーを出力します。 Console.WriteLine("Request headers:"); foreach (var header in request.Content.Headers) { Console.WriteLine($"{header.Key}: {string.Join(", ", header.Value)}"); } // リクエストを送信します。 var response = await httpClient.SendAsync(request); // 応答を処理します。 if (response.IsSuccessStatusCode) { Console.WriteLine($"Upload successful! Status code: {response.StatusCode}"); Console.WriteLine("Response headers:"); foreach (var header in response.Headers) { Console.WriteLine($"{header.Key}: {string.Join(", ", header.Value)}"); } } else { string responseContent = await response.Content.ReadAsStringAsync(); Console.WriteLine($"Upload failed! Status code: {response.StatusCode}"); Console.WriteLine("Response content: " + responseContent); }C++
#include <iostream> #include <fstream> #include <curl/curl.h> #include <map> #include <string> // HTTP 応答を処理するコールバック関数。 size_t WriteCallback(void* contents, size_t size, size_t nmemb, std::string* output) { size_t totalSize = size * nmemb; output->append((char*)contents, totalSize); return totalSize; } void uploadFile(const std::string& signedUrl, const std::string& filePath, const std::map<std::string, std::string>& headers, const std::map<std::string, std::string>& metadata) { CURL* curl; CURLcode res; std::string readBuffer; curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); if (curl) { // URL を設定します。 curl_easy_setopt(curl, CURLOPT_URL, signedUrl.c_str()); // リクエストメソッドを PUT に設定します。 curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); // ファイルを開きます。 FILE* file = fopen(filePath.c_str(), "rb"); if (!file) { std::cerr << "Unable to open file: " << filePath << std::endl; return; } // ファイルサイズを設定します。 fseek(file, 0, SEEK_END); long fileSize = ftell(file); rewind(file); // ファイル読み取りコールバックを設定します。 curl_easy_setopt(curl, CURLOPT_READDATA, file); curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)fileSize); // リクエストヘッダーを設定します。 struct curl_slist* chunk = nullptr; for (const auto& header : headers) { std::string headerStr = header.first + ": " + header.second; chunk = curl_slist_append(chunk, headerStr.c_str()); } for (const auto& meta : metadata) { std::string metaStr = "x-oss-meta-" + meta.first + ": " + meta.second; chunk = curl_slist_append(chunk, metaStr.c_str()); } curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk); // 応答処理コールバックを設定します。 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer); // リクエストを実行します。 res = curl_easy_perform(curl); // 応答を確認します。 if (res != CURLE_OK) { std::cerr << "curl_easy_perform() failed: " << curl_easy_strerror(res) << std::endl; } else { long responseCode; curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &responseCode); std::cout << "Status code returned for the upload: " << responseCode << std::endl; if (responseCode == 200) { std::cout << "Upload successful using network library." << std::endl; } else { std::cout << "Upload failed." << std::endl; } std::cout << readBuffer << std::endl; } // クリーンアップします。 fclose(file); curl_slist_free_all(chunk); curl_easy_cleanup(curl); } curl_global_cleanup(); } int main() { // <signedUrl> を承認済み URL に置き換えます。 std::string signedUrl = "<signedUrl>"; // ローカルファイルの完全なパスを指定します。ローカルパスを指定しない場合、ファイルはサンプルプログラムのプロジェクトパスからデフォルトでアップロードされます。 std::string filePath = "C:\\Users\\demo.txt"; // リクエストヘッダーを設定します。リクエストヘッダー情報は、URL が生成されたときに使用された情報と同じでなければなりません。 std::map<std::string, std::string> headers = { {"Content-Type", "text/plain;charset=utf8"}, {"x-oss-storage-class", "Standard"} }; // カスタムユーザーメタデータを設定します。カスタムユーザーメタデータは、URL が生成されたときに使用された情報と同じでなければなりません。 std::map<std::string, std::string> metadata = { {"key1", "value1"}, {"key2", "value2"} }; uploadFile(signedUrl, filePath, headers, metadata); return 0; }Android
import android.os.AsyncTask; import android.util.Log; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; public class SignUrlUploadActivity extends AppCompatActivity { private static final String TAG = "SignUrlUploadActivity"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // <signedUrl> を承認済み URL に置き換えます。 String signedUrl = "<signedUrl>"; // ローカルファイルの完全なパスを指定します。ローカルパスを指定しない場合、ファイルはサンプルプログラムのプロジェクトパスからデフォルトでアップロードされます。 String pathName = "/storage/emulated/0/demo.txt"; // リクエストヘッダーを設定します。リクエストヘッダー情報は、URL が生成されたときに使用された情報と同じでなければなりません。 Map<String, String> headers = new HashMap<>(); headers.put("Content-Type", "text/plain;charset=utf8"); headers.put("x-oss-storage-class", "Standard"); // カスタムユーザーメタデータを設定します。カスタムユーザーメタデータは、URL が生成されたときに使用された情報と同じでなければなりません。 Map<String, String> userMetadata = new HashMap<>(); userMetadata.put("key1", "value1"); userMetadata.put("key2", "value2"); new UploadTask().execute(signedUrl, pathName, headers, userMetadata); } private class UploadTask extends AsyncTask<Object, Void, Integer> { @Override protected Integer doInBackground(Object... params) { String signedUrl = (String) params[0]; String pathName = (String) params[1]; Map<String, String> headers = (Map<String, String>) params[2]; Map<String, String> userMetadata = (Map<String, String>) params[3]; try { URL url = new URL(signedUrl); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("PUT"); connection.setDoOutput(true); connection.setUseCaches(false); // リクエストヘッダーを設定します。 for (Entry<String, String> header : headers.entrySet()) { connection.setRequestProperty(header.getKey(), header.getValue()); } // カスタムユーザーメタデータを設定します。 for (Entry<String, String> meta : userMetadata.entrySet()) { connection.setRequestProperty("x-oss-meta-" + meta.getKey(), meta.getValue()); } // ファイルを読み取ります。 File file = new File(pathName); FileInputStream fileInputStream = new FileInputStream(file); DataOutputStream dos = new DataOutputStream(connection.getOutputStream()); byte[] buffer = new byte[1024]; int count; while ((count = fileInputStream.read(buffer)) != -1) { dos.write(buffer, 0, count); } fileInputStream.close(); dos.flush(); dos.close(); // 応答を取得します。 int responseCode = connection.getResponseCode(); Log.d(TAG, "Status code returned for the upload: " + responseCode); if (responseCode == 200) { Log.d(TAG, "Upload successful using network library."); } else { Log.d(TAG, "Upload failed."); } InputStream is = connection.getInputStream(); byte[] responseBuffer = new byte[1024]; StringBuilder responseStringBuilder = new StringBuilder(); while ((count = is.read(responseBuffer)) != -1) { responseStringBuilder.append(new String(responseBuffer, 0, count)); } Log.d(TAG, responseStringBuilder.toString()); return responseCode; } catch (IOException e) { e.printStackTrace(); return -1; } } @Override protected void onPostExecute(Integer result) { super.onPostExecute(result); if (result == 200) { Toast.makeText(SignUrlUploadActivity.this, "Upload successful.", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(SignUrlUploadActivity.this, "Upload failed.", Toast.LENGTH_SHORT).show(); } } } }
アップロードコールバックの設定
ファイルをアップロードする際に、コールバックパラメーターを追加して、アップロードが成功した後にアプリケーションサーバーに自動的に通知することができます。コールバックの原則の詳細については、「コールバック」をご参照ください。
バケットのオーナーが、アップロードコールバックパラメーターを含む PUT リクエスト用の署名付き URL を生成します。
Python
import argparse import base64 import requests import alibabacloud_oss_v2 as oss from datetime import datetime, timedelta # コマンドラインパラメーターパーサーを作成し、スクリプトの目的を記述します。この例では、HTTP PUT リクエストを許可する署名付き URL を生成する方法を説明します。 parser = argparse.ArgumentParser(description="presign put object sample") # 必須のリージョン、バケット名、エンドポイント、オブジェクト名を含むコマンドラインパラメーターを指定します。 parser.add_argument('--region', help='The region in which the bucket is located.', required=True) parser.add_argument('--bucket', help='The name of the bucket.', required=True) parser.add_argument('--endpoint', help='The domain names that other services can use to access OSS') parser.add_argument('--key', help='The name of the object.', required=True) def main(): # コマンドラインパラメーターを解析します。 args = parser.parse_args() # 認証のために環境変数からアクセス認証情報を取得します。 credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider() # デフォルト構成を使用して cfg オブジェクトを作成し、認証情報プロバイダーを指定します。 cfg = oss.config.load_default() cfg.credentials_provider = credentials_provider # cfg オブジェクトのリージョン属性をコマンドラインで提供されたリージョンに設定します。 cfg.region = args.region # カスタムエンドポイントが提供されている場合は、cfg オブジェクトのエンドポイント属性を更新します。 if args.endpoint is not None: cfg.endpoint = args.endpoint # 上記の構成を使用して OSSClient インスタンスを初期化します。 client = oss.Client(cfg) # カスタムコールバック URL を指定します。 call_back_url = "http://www.example.com/callback" # コールバックパラメーターを構築します: コールバック URL とリクエストボディを指定し、パラメーターを Base64 でエンコードします。 callback=base64.b64encode(str('{\"callbackUrl\":\"' + call_back_url + '\",\"callbackBody\":\"bucket=${bucket}&object=${object}&my_var_1=${x:var1}&my_var_2=${x:var2}\"}').encode()).decode() # カスタムコールバック変数を定義し、Base64 でエンコードします。 callback_var=base64.b64encode('{\"x:var1\":\"value1\",\"x:var2\":\"value2\"}'.encode()).decode() # PUT リクエストを開始し、指定されたオブジェクトの署名付き URL を生成するリクエストを送信します。 pre_result = client.presign(oss.PutObjectRequest( bucket=args.bucket, # バケットの名前。 key=args.key, # オブジェクトの名前。 callback=callback, callback_var=callback_var, ),expires=timedelta(seconds=3600)) # リクエストの有効期間を指定します。この例では、有効期間は 3,600 秒に設定されています。 # リクエストで指定されたメソッド、有効期限、署名付き URL を表示して、署名付き URL の有効性を確認します。 print(f'method: {pre_result.method},' f' expiration: {pre_result.expiration.strftime("%Y-%m-%dT%H:%M:%S.000Z")},' f' url: {pre_result.url}' ) # リクエストの署名付きヘッダーを表示します。これは、リクエストが送信されるときに HTTP ヘッダーに含まれます。 for key, value in pre_result.signed_headers.items(): print(f'signed headers key: {key}, signed headers value: {value}') # スクリプトが直接実行されるときに処理ロジックを開始するために main 関数を呼び出します。 if __name__ == "__main__": main() # スクリプトのエントリポイントを指定します。制御フローはここから始まります。Go
package main import ( "context" "encoding/base64" "encoding/json" "flag" "log" "time" "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() // バケットの名前が指定されているかどうかを確認します。 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) // コールバックパラメーターを指定します。 callbackMap := map[string]string{ "callbackUrl": "http://example.com:23450", // コールバックサーバーの URL を指定します。例: https://example.com:23450。 "callbackBody": "bucket=${bucket}&object=${object}&size=${size}&my_var_1=${x:my_var1}&my_var_2=${x:my_var2}", // コールバックリクエストボディを指定します。 "callbackBodyType": "application/x-www-form-urlencoded", // コールバックリクエストボディのタイプを指定します。 } // コールバックパラメーターの構成を JSON 文字列に変換し、その文字列を Base64 でエンコードしてコールバック構成を渡します。 callbackStr, err := json.Marshal(callbackMap) if err != nil { log.Fatalf("failed to marshal callback map: %v", err) } callbackBase64 := base64.StdEncoding.EncodeToString(callbackStr) callbackVarMap := map[string]string{} callbackVarMap["x:my_var1"] = "thi is var 1" callbackVarMap["x:my_var2"] = "thi is var 2" callbackVarStr, err := json.Marshal(callbackVarMap) if err != nil { log.Fatalf("failed to marshal callback var: %v", err) } callbackVarBase64 := base64.StdEncoding.EncodeToString(callbackVarStr) // PutObject リクエスト用の署名付き URL を生成します。 result, err := client.Presign(context.TODO(), &oss.PutObjectRequest{ Bucket: oss.Ptr(bucketName), Key: oss.Ptr(objectName), Callback: oss.Ptr(callbackBase64), // コールバックパラメーターを設定します。この場合は Base64 エンコードされた JSON 文字列です。 CallbackVar: oss.Ptr(callbackVarBase64), // コールバックリクエストのカスタムパラメーターを指定します。この例では Base64 エンコードされた JSON 文字列です。 }, oss.PresignExpires(10*time.Minute), ) if err != nil { log.Fatalf("failed to put object presign %v", err) } log.Printf("request method:%v\n", result.Method) log.Printf("request expiration:%v\n", result.Expiration) log.Printf("request url:%v\n", result.URL) if len(result.SignedHeaders) > 0 { // HTTP PUT リクエストを許可する署名付き URL を生成する際にリクエストヘッダーを指定する場合は、そのリクエストヘッダーが署名付き URL を使用して開始される PUT リクエストに含まれていることを確認してください。 log.Printf("signed headers:\n") for k, v := range result.SignedHeaders { log.Printf("%v: %v\n", k, v) } } }Java
import com.aliyun.oss.*; import com.aliyun.oss.common.auth.CredentialsProviderFactory; import com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider; import com.aliyun.oss.common.comm.SignVersion; import com.aliyun.oss.internal.OSSHeaders; import com.aliyun.oss.model.GeneratePresignedUrlRequest; import java.net.URL; import java.text.SimpleDateFormat; import java.util.*; public class OssPresignExample { public static void main(String[] args) throws Throwable { // この例では、中国 (杭州) リージョンのパブリックエンドポイントを使用します。実際のエンドポイントを指定してください。 String endpoint = "https://oss-cn-hangzhou.aliyuncs.com"; // 環境変数からアクセス認証情報を取得します。サンプルコードを実行する前に、OSS_ACCESS_KEY_ID および OSS_ACCESS_KEY_SECRET 環境変数が設定されていることを確認してください。 EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider(); // バケット名を指定します (例: examplebucket)。 String bucketName = "examplebucket"; // オブジェクトの完全なパスを指定します (例: exampleobject.txt)。オブジェクトの完全なパスにバケット名を含めることはできません。 String objectName = "exampleobject.txt"; // バケットが配置されているリージョンを指定します。たとえば、バケットが中国 (杭州) リージョンにある場合、リージョンを 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(); URL signedUrl = null; try { // コールバックパラメーターを構築します。 String callbackUrl = "http://www.example.com/callback"; String callbackBody = "{\"callbackUrl\":\"" + callbackUrl + "\",\"callbackBody\":\"bucket=${bucket}&object=${object}&my_var_1=${x:var1}&my_var_2=${x:var2}\"}"; String callbackBase64 = Base64.getEncoder().encodeToString(callbackBody.getBytes()); String callbackVarJson = "{\"x:var1\":\"value1\",\"x:var2\":\"value2\"}"; String callbackVarBase64 = Base64.getEncoder().encodeToString(callbackVarJson.getBytes()); // リクエストヘッダーを設定します。 Map<String, String> headers = new HashMap<String, String>(); // CALLBACK を指定します。 headers.put(OSSHeaders.OSS_HEADER_CALLBACK, callbackBase64); // CALLBACK-VAR を指定します。 headers.put(OSSHeaders.OSS_HEADER_CALLBACK_VAR, callbackVarBase64); // 有効期限を設定します (3600 秒後)。 Date expiration = new Date(new Date().getTime() + 3600 * 1000); // 有効期限をフォーマットします。 SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); String expirationStr = dateFormat.format(expiration); // リクエストを構築します。 GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucketName, objectName); request.setMethod(HttpMethod.PUT); request.setExpiration(expiration); // リクエストにリクエストヘッダーを追加します。 request.setHeaders(headers); // callback および callback-var パラメーターを出力します。 System.out.println("callback:"+callbackBase64); System.out.println("callback-var:"+callbackVarBase64); // 署名付き URL を生成します。 URL url = ossClient.generatePresignedUrl(request); // 結果を出力します。 System.out.println("method: PUT,"); System.out.println(" expiration: " + expirationStr + ","); System.out.println(" url: " + url); } 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()); } } }PHP
<?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); // x-oss-callback および x-oss-callback-var ヘッダーを含めます。 // コールバック URL を指定します。 $call_back_url = "http://www.example.com/callback"; // コールバックパラメーターを構築します: コールバック URL とリクエストボディを指定し、両方とも Base64 でエンコードする必要があります。 // ${x:var1} と ${x:var2} をプレースホルダー {var1} と {var2} に置き換えます。 $callback_body_template = "bucket={bucket}&object={object}&my_var_1={var1}&my_var_2={var2}"; $callback_body_replaced = str_replace( ['{bucket}', '{object}', '{var1}', '{var2}'], [$bucket, $key, 'value1', 'value2'], $callback_body_template ); $callback = base64_encode(json_encode([ "callbackUrl" => $call_back_url, "callbackBody" => $callback_body_replaced ])); // カスタムコールバック変数を定義し、Base64 でエンコードします。 $callback_var = base64_encode(json_encode([ "x:var1" => "value1", "x:var2" => "value2" ])); // データをアップロードするための PutObjectRequest オブジェクトを作成します。 // Content-Type、メタデータ、およびヘッダーが署名計算に含まれることに注意してください。 $request = new Oss\Models\PutObjectRequest( bucket: $bucket, key: $key, callback:$callback, callbackVar:$callback_var, ); // presign メソッドを呼び出して、署名付きリクエストを生成します。 $result = $client->presign($request); // 指定されたオブジェクトをアップロードするために使用できる署名付き URL を表示します。 print( 'put object presign result:' . var_export($result, true) . PHP_EOL . 'put object url:' . $result->url . PHP_EOL );サードパーティが PUT リクエスト用の署名付き URL を使用してファイルをアップロードします。
curl
curl -X PUT \ -H "x-oss-callback: eyJjYWxsYmFja1VybCI6Imh0dHA6Ly93d3cuZXhhbXBsZS5jb20vY2FsbGJhY2siLCJjYWxsYmFja0JvZHkiOiJidWNrZXQ9JHtidWNrZXR9Jm9iamVjdD0ke29iamVjdH0mbXlfdmFyXzE9JHt4OnZhcjF9Jm15X3Zhcl8yPSR7eDp2YXIyfSJ9" \ -H "x-oss-callback-var: eyJ4OnZhcjEiOiJ2YWx1ZTEiLCJ4OnZhcjIiOiJ2YWx1ZTIifQ==" \ -T "C:\\Users\\demo.txt" \ "https://exampleobject.oss-cn-hangzhou.aliyuncs.com/exampleobject.txt?x-oss-date=20241112T083238Z&x-oss-expires=3599&x-oss-signature-version=OSS4-HMAC-SHA256&x-oss-credential=LTAI****************%2F20241112%2Fcn-hangzhou%2Foss%2Faliyun_v4_request&x-oss-signature=ed5a******************************************************"Python
import requests def upload_file(signed_url, file_path, headers=None): """ 署名付き URL を使用してオブジェクトを OSS にアップロードします。 :param signed_url: 署名付き URL。 :param file_path: アップロードするローカルファイルの完全なパス。 :param headers: リクエストヘッダー。このパラメーターはオプションです。 :return: None """ if not headers: headers = {} try: with open(file_path, 'rb') as file: response = requests.put(signed_url, data=file, headers=headers) print(f"Status code: {response.status_code}") if response.status_code == 200: print("The object is uploaded by using the library.") else: print("Upload failed.") print(response.text) except Exception as e: print(f"An error occurred: {e}") if __name__ == "__main__": # <signedUrl> を署名付き URL に置き換えます。 signed_url = "<signedUrl>" # ローカルファイルの完全なパスを指定します。デフォルトでは、ローカルファイルの完全なパスを指定しない場合、ローカルファイルはスクリプトが保存されているディレクトリからアップロードされます。 file_path = "C:\\Users\\demo.txt" headers = { "x-oss-callback": "eyJjYWxsYmFja1VybCI6Imh0dHA6Ly93d3cuZXhhbXBsZS5jb20vY2FsbGJhY2siLCJjYWxsYmFja0JvZHkiOiJidWNrZXQ9JHtidWNrZXR9Jm9iamVjdD0ke29iamVjdH0mbXlfdmFyXzE9JHt4OnZhcjF9Jm15X3Zhcl8yPSR7eDp2YXIyfSJ9", "x-oss-callback-var": "eyJ4OnZhcjEiOiJ2YWx1ZTEiLCJ4OnZhcjIiOiJ2YWx1ZTIifQ==", } upload_file(signed_url, file_path, headers)Go
package main import ( "bytes" "fmt" "io" "net/http" "os" ) func uploadFile(signedUrl string, filePath string, headers map[string]string) error { // ファイルを開きます。 file, err := os.Open(filePath) if err != nil { return err } defer file.Close() // コンテンツを読み取ります。 fileBytes, err := io.ReadAll(file) if err != nil { return err } // リクエストを作成します。 req, err := http.NewRequest("PUT", signedUrl, bytes.NewBuffer(fileBytes)) if err != nil { return err } // リクエストヘッダーを指定します。 for key, value := range headers { req.Header.Add(key, value) } // リクエストを送信します。 client := &http.Client{} resp, err := client.Do(req) if err != nil { return err } defer resp.Body.Close() // 応答を処理します。 fmt.Printf("Status code: %d\n", resp.StatusCode) if resp.StatusCode == 200 { fmt.Println("The object is uploaded by using the library.") } else { fmt.Println("Upload failed.") } body, _ := io.ReadAll(resp.Body) fmt.Println(string(body)) return nil } func main() { // <signedUrl> を署名付き URL に置き換えます。 signedUrl := "<signedUrl>" // ローカルファイルの完全なパスを指定します。ローカルファイルのパスが指定されていない場合、ローカルファイルはサンプルプログラムが属するプロジェクトのパスからアップロードされます。 filePath := "C:\\Users\\demo.txt" // リクエストヘッダーを指定します。リクエストヘッダーの値が、署名付き URL が生成されたときに指定された値と同じであることを確認してください。 headers := map[string]string{ "x-oss-callback": "eyJjYWxsYmFja1VybCI6Imh0dHA6Ly93d3cuZXhhbXBsZS5jb20vY2FsbGJhY2siLCJjYWxsYmFja0JvZHkiOiJidWNrZXQ9JHtidWNrZXR9Jm9iamVjdD0ke29iamVjdH0mbXlfdmFyXzE9JHt4OnZhcjF9Jm15X3Zhcl8yPSR7eDp2YXIyfSJ9", "x-oss-callback-var": "eyJ4OnZhcjEiOiJ2YWx1ZTEiLCJ4OnZhcjIiOiJ2YWx1ZTIifQ==", } err := uploadFile(signedUrl, filePath, headers) if err != nil { fmt.Printf("An error occurred: %v\n", err) } }Java
import org.apache.http.HttpEntity; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpPut; import org.apache.http.entity.FileEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import java.io.*; import java.net.URL; import java.util.*; public class SignUrlUpload { public static void main(String[] args) throws Throwable { CloseableHttpClient httpClient = null; CloseableHttpResponse response = null; // <signedUrl> を署名付き URL に置き換えます。 URL signedUrl = new URL("<signedUrl>"); // ローカルファイルの完全なパスを指定します。ローカルファイルのパスが指定されていない場合、ローカルファイルはサンプルプログラムが属するプロジェクトのパスからアップロードされます。 String pathName = "C:\\Users\\demo.txt"; // x-oss-callback および x-oss-callback-var を含むリクエストヘッダーを指定します。 Map<String, String> headers = new HashMap<String, String>(); headers.put("x-oss-callback", "eyJjYWxsYmFja1VybCI6Imh0dHA6Ly93d3cuZXhhbXBsZS5jb20vY2FsbGJhY2siLCJjYWxsYmFja0JvZHkiOiJidWNrZXQ9JHtidWNrZXR9Jm9iamVjdD0ke29iamVjdH0mbXlfdmFyXzE9JHt4OnZhcjF9Jm15X3Zhcl8yPSR7eDp2YXIyfSJ9"); headers.put("x-oss-callback-var", "eyJ4OnZhcjEiOiJ2YWx1ZTEiLCJ4OnZhcjIiOiJ2YWx1ZTIifQ=="); try { HttpPut put = new HttpPut(signedUrl.toString()); System.out.println(put); HttpEntity entity = new FileEntity(new File(pathName)); put.setEntity(entity); // 署名付き URL が生成されたときにヘッダーを設定した場合、署名付き URL を使用してファイルをアップロードする際にこれらのヘッダーをサーバーに送信する必要があります。署名計算のためにサーバーに送信されるヘッダーが、署名付き URL が生成されたときに指定されたヘッダーと異なる場合、署名エラーが報告されます。 for(Map.Entry header: headers.entrySet()){ put.addHeader(header.getKey().toString(),header.getValue().toString()); } httpClient = HttpClients.createDefault(); response = httpClient.execute(put); System.out.println("Status code: "+response.getStatusLine().getStatusCode()); if(response.getStatusLine().getStatusCode() == 200){ System.out.println("The object is uploaded by using the library."); } System.out.println(response.toString()); } catch (Exception e){ e.printStackTrace(); } finally { response.close(); httpClient.close(); } } }PHP
<?php function uploadFile($signedUrl, $filePath, $headers = []) { // ファイルが存在するかどうかを確認します。 if (!file_exists($filePath)) { echo "The file does not exist: $filePath\n"; return; } // cURL セッションを初期化します。 $ch = curl_init(); // cURL オプションを設定します。 curl_setopt($ch, CURLOPT_URL, $signedUrl); curl_setopt($ch, CURLOPT_PUT, true); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_INFILE, fopen($filePath, 'rb')); curl_setopt($ch, CURLOPT_INFILESIZE, filesize($filePath)); curl_setopt($ch, CURLOPT_HTTPHEADER, array_map(function($key, $value) { return "$key: $value"; }, array_keys($headers), $headers)); // cURL リクエストを実行します。 $response = curl_exec($ch); // HTTP ステータスコードを照会します。 $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); // cURL セッションを閉じます。 curl_close($ch); // 結果を出力します echo "Status code: $httpCode\n"; if ($httpCode == 200) { echo "The object is uploaded by using the library.\n"; } else { echo "Upload failed.\n"; } echo $response . "\n"; } // <signedUrl> を署名付き URL に置き換えます。 $signedUrl = "<signedUrl>"; // ローカルファイルの完全なパスを指定します。デフォルトでは、ローカルファイルの完全なパスを指定しない場合、ローカルファイルはスクリプトが保存されているディレクトリからアップロードされます。 $filePath = "C:\\Users\\demo.txt"; $headers = [ "x-oss-callback" => "eyJjYWxsYmFja1VybCI6Imh0dHA6Ly93d3cuZXhhbXBsZS5jb20vY2FsbGJhY2siLCJjYWxsYmFja0JvZHkiOiJidWNrZXQ9JHtidWNrZXR9Jm9iamVjdD0ke29iamVjdH0mbXlfdmFyXzE9JHt4OnZhcjF9Jm15X3Zhcl8yPSR7eDp2YXIyfSJ9", "x-oss-callback-var" => "eyJ4OnZhcjEiOiJ2YWx1ZTEiLCJ4OnZhcjIiOiJ2YWx1ZTIifQ==", ]; uploadFile($signedUrl, $filePath, $headers); ?>
詳細情報
署名付き URL とは
署名付き URL は、暗号化された署名と有効期間の検証を使用して、特定の OSS ファイルへの一時的なアクセスを許可する安全なリンクです。署名付き URL が生成されると、AccessKey ペア、リソースパス、有効期限、その他のパラメーターに基づいて、暗号化された署名がローカルで計算されます。その後、署名パラメーターが URL に追加され、完全な署名付き URL が形成されます。一般的な形式は次のとおりです:https://BucketName.Endpoint/Object?signature_parameters。
サードパーティがこの URL にアクセスすると、OSS は署名パラメーターを検証します。パラメーターが改ざんされているか、URL の有効期限が切れている場合、アクセスは拒否されます。
以下は署名付き URL の例です。
https://examplebucket.oss-cn-hangzhou.aliyuncs.com/exampleobject.txt?x-oss-process=image%2Fresize%2Cp_10&x-oss-date=20241115T095058Z&x-oss-expires=3600&x-oss-signature-version=OSS4-HMAC-SHA256&x-oss-credential=LTAI****************%2F20241115%2Fcn-hangzhou%2Foss%2Faliyun_v4_request&x-oss-signature=6e7a********************************この方法により、バケットのオーナーは AccessKey ペアを公開することなく、サードパーティのファイルへのアクセスを安全に許可できます。
シナリオ
短期的なファイル共有:サードパーティが特定のファイルのアップロードまたはダウンロードをリクエストします。バックエンドは有効期間付きの署名付き URL を生成し、フロントエンドに返します。サードパーティはこの URL を使用して、有効期間内にファイルをアップロードまたはダウンロードでき、データのセキュリティが確保されます。
柔軟なアクセス:バケットのオーナーは、メールやチャットを通じて署名付き URL を共有できます。サードパーティは、URL をブラウザのアドレスバーに貼り付けてファイルをダウンロードできます。