デフォルトでは、Object Storage Service (OSS) バケット内のオブジェクトのアクセス制御リスト (ACL) は非公開です。オブジェクト所有者のみがオブジェクトにアクセスする権限を持っています。このトピックでは、OSS SDK for Python を使用して、ユーザーが HTTP GET メソッドを使用して指定された期間内に特定のオブジェクトをダウンロードできる署名付き URL を生成する方法について説明します。有効期間内であれば、ユーザーは署名付き URL を使用してオブジェクトに繰り返しアクセスできます。署名付き URL の有効期限が切れた場合、署名付き URL を再生成してユーザーのアクセスを延長できます。
使用上の注意
このトピックのサンプルコードでは、中国 (杭州) リージョンのリージョン ID
cn-hangzhouを使用します。デフォルトでは、バケット内のリソースへのアクセスにはパブリックエンドポイントが使用されます。バケットが配置されているリージョンと同じリージョン内の他の Alibaba Cloud サービスからバケット内のリソースにアクセスする場合は、内部エンドポイントを使用します。OSS のリージョンとエンドポイントの詳細については、「リージョンとエンドポイント」をご参照ください。署名付き URL を生成するために特別な権限は必要ありません。ただし、他のユーザーが署名付き URL を使用してオブジェクトをダウンロードできるようにするには、
oss:GetObject権限が必要です。詳細については、「RAM ポリシーの一般的な例」をご参照ください。このトピックでは、署名アルゴリズム V4 を使用して、最大 7 日間の有効期間を持つ署名付き URL を生成します。詳細については、「(推奨) 署名付き URL の V4 署名」をご参照ください。
プロセス
次のフローチャートは、署名付き URL を使用してオブジェクトをダウンロードする方法を示しています。
メソッドの定義
presign メソッドを呼び出して、OSS オブジェクトへの時間制限付きアクセスを許可する署名付き URL を生成できます。署名付き URL は、有効期限が切れるまで複数回使用できます。
次の行は、presign メソッドの構文を示しています:
presign(request: GetObjectRequest, **kwargs) → PresignResultリクエストパラメーター
パラメーター | タイプ | 説明 |
request | GetObjectRequest | 署名付き URL でサポートする API 操作。詳細については、「Client.presign」をご参照ください。 |
expires | datetime.timedelta | 現在時刻から始まる署名付き URL の有効期間。これはオプションのパラメーターです。たとえば、有効期間を 30 分に設定する場合は、expires を 30 * time.Minute に設定します。このパラメーターを指定しない場合、署名付き URL のデフォルトの有効期間は 15 分になります。 |
expiration | datetime.datetime | 署名付き URL の絶対有効期限日時。これはオプションのパラメーターです。 |
V4 署名アルゴリズムを使用する場合、有効期間は最大 7 日間です。expiration と expires の両方を指定した場合、expiration が優先されます。
応答パラメーター
タイプ | 説明 |
PresignResult | 返される結果には、署名付き URL、HTTP メソッド、有効期限、リクエストで指定されたリクエストヘッダーが含まれます。詳細については、「PresignResult」をご参照ください。 |
PresignResult の内容
パラメーター | タイプ | 説明 |
method | str | presign リクエストで指定された API 操作に対応する HTTP メソッド。たとえば、GetObject 操作の HTTP メソッドは GET です。 |
url | str | 署名付き URL。 |
expiration | datetime | 署名付き URL の有効期限。 |
signed_headers | MutableMapping | リクエストで指定された署名付きヘッダー。たとえば、content_type が指定されている場合、content_type が返されます。 |
presign メソッドの詳細については、「presign」をご参照ください。
サンプルコード
HTTP GET リクエストを許可する署名付き URL を生成します:
import argparse import alibabacloud_oss_v2 as oss # コマンドラインパラメーターパーサーを作成し、スクリプトの目的を記述します。 parser = argparse.ArgumentParser(description="presign get object sample") # --region パラメーターを指定して、バケットが配置されているリージョンを示します。このパラメーターは必須です。 parser.add_argument('--region', help='The region in which the bucket is located.', required=True) # --bucket パラメーターを指定して、オブジェクトが格納されているバケットの名前を示します。このパラメーターは必須です。 parser.add_argument('--bucket', help='The name of the bucket.', required=True) # --endpoint パラメーターを指定して、バケットが配置されているリージョンのエンドポイントを示します。このパラメーターはオプションです。 parser.add_argument('--endpoint', help='The domain names that other services can use to access OSS') # --key パラメーターを指定して、オブジェクトの名前を示します。このパラメーターは必須です。 parser.add_argument('--key', help='The name of the object.', required=True) def main(): # コマンドラインパラメーターを解析して、指定された値を取得します。 args = parser.parse_args() # 環境変数から、OSS へのアクセスに必要な認証情報を読み込みます。 credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider() # デフォルトの構成を使用して cfg オブジェクトを作成し、資格情報プロバイダーを指定します。 cfg = oss.config.load_default() cfg.credentials_provider = credentials_provider # cfg オブジェクトの region 属性を、コマンドラインで指定されたリージョンに設定します。 cfg.region = args.region # カスタムエンドポイントが指定されている場合は、cfg オbジェクトの endpoint 属性を指定されたエンドポイントで更新します。 if args.endpoint is not None: cfg.endpoint = args.endpoint # 上記の設定を使用して OSSClient インスタンスを初期化します。 client = oss.Client(cfg) # 署名付き URL を生成するリクエストを開始します。 pre_result = client.presign( oss.GetObjectRequest( bucket=args.bucket, # バケット名を指定します。 key=args.key, # オブジェクトキーを指定します。 ) ) # HTTP メソッド、有効期限、署名付き 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}' ) # 署名付きヘッダーを表示します。 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 -SO "https://examplebucket.oss-cn-hangzhou.aliyuncs.com/exampleobject.txt?x-oss-date=20241112T092756Z&x-oss-expires=3599&x-oss-signature-version=OSS4-HMAC-SHA256&x-oss-credential=LTAI****************/20241112/cn-hangzhou/oss/aliyun_v4_request&x-oss-signature=ed5a******************************************************"Java
import java.io.BufferedInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; public class Demo { public static void main(String[] args) { // HTTP GET リクエストを許可する署名付き URL を指定します。 String fileURL = "https://examplebucket.oss-cn-hangzhou.aliyuncs.com/exampleobject.txt?x-oss-date=20241112T092756Z&x-oss-expires=3599&x-oss-signature-version=OSS4-HMAC-SHA256&x-oss-credential=LTAI****************/20241112/cn-hangzhou/oss/aliyun_v4_request&x-oss-signature=ed5a******************************************************"; // ダウンロードしたオブジェクトを格納するパスを、オブジェクト名と拡張子を含めて指定します。 String savePath = "C:/downloads/myfile.txt"; try { downloadFile(fileURL, savePath); System.out.println("Download completed!"); } catch (IOException e) { System.err.println("Error during download: " + e.getMessage()); } } private static void downloadFile(String fileURL, String savePath) throws IOException { URL url = new URL(fileURL); HttpURLConnection httpConn = (HttpURLConnection) url.openConnection(); httpConn.setRequestMethod("GET"); // 応答コードを指定します。 int responseCode = httpConn.getResponseCode(); if (responseCode == HttpURLConnection.HTTP_OK) { // 入力ストリームを構成します。 InputStream inputStream = new BufferedInputStream(httpConn.getInputStream()); // 出力ストリームを構成します。 FileOutputStream outputStream = new FileOutputStream(savePath); byte[] buffer=new byte[4096]; // バッファーのサイズを指定します。 int bytesRead; while ((bytesRead = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, bytesRead); } outputStream.close(); inputStream.close(); } else { System.out.println("No file to download. Server replied HTTP code: " + responseCode); } httpConn.disconnect(); } }Node.js
const https = require('https'); const fs = require('fs'); const fileURL = "https://examplebucket.oss-cn-hangzhou.aliyuncs.com/exampleobject.txt?x-oss-date=20241112T092756Z&x-oss-expires=3599&x-oss-signature-version=OSS4-HMAC-SHA256&x-oss-credential=LTAI****************/20241112/cn-hangzhou/oss/aliyun_v4_request&x-oss-signature=ed5a******************************************************"; const savePath = "C:/downloads/myfile.txt"; https.get(fileURL, (response) => { if (response.statusCode === 200) { const fileStream = fs.createWriteStream(savePath); response.pipe(fileStream); fileStream.on('finish', () => { fileStream.close(); console.log("Download completed!"); }); } else { console.error(`Download failed. Server responded with code: ${response.statusCode}`); } }).on('error', (err) => { console.error("Error during download:", err.message); });Python
import requests file_url = "https://examplebucket.oss-cn-hangzhou.aliyuncs.com/exampleobject.txt?x-oss-date=20241112T092756Z&x-oss-expires=3599&x-oss-signature-version=OSS4-HMAC-SHA256&x-oss-credential=LTAI****************/20241112/cn-hangzhou/oss/aliyun_v4_request&x-oss-signature=ed5a******************************************************" save_path = "C:/downloads/myfile.txt" try: response = requests.get(file_url, stream=True) if response.status_code == 200: with open(save_path, 'wb') as f: for chunk in response.iter_content(4096): f.write(chunk) print("Download completed!") else: print(f"No file to download. Server replied HTTP code: {response.status_code}") except Exception as e: print("Error during download:", e)Go
package main import ( "io" "net/http" "os" ) func main() { fileURL := "https://examplebucket.oss-cn-hangzhou.aliyuncs.com/exampleobject.txt?x-oss-date=20241112T092756Z&x-oss-expires=3599&x-oss-signature-version=OSS4-HMAC-SHA256&x-oss-credential=LTAI****************/20241112/cn-hangzhou/oss/aliyun_v4_request&x-oss-signature=ed5a******************************************************" savePath := "C:/downloads/myfile.txt" response, err := http.Get(fileURL) if err != nil { panic(err) } defer response.Body.Close() if response.StatusCode == http.StatusOK { outFile, err := os.Create(savePath) if err != nil { panic(err) } defer outFile.Close() _, err = io.Copy(outFile, response.Body) if err != nil { panic(err) } println("Download completed!") } else { println("No file to download. Server replied HTTP code:", response.StatusCode) } }JavaScript
const fileURL = "https://examplebucket.oss-cn-hangzhou.aliyuncs.com/exampleobject.txt?x-oss-date=20241112T092756Z&x-oss-expires=3599&x-oss-signature-version=OSS4-HMAC-SHA256&x-oss-credential=LTAI****************/20241112/cn-hangzhou/oss/aliyun_v4_request&x-oss-signature=ed5a******************************************************"; const savePath = "C:/downloads/myfile.txt"; // ダウンロードしたオブジェクトの名前を指定します。 fetch(fileURL) .then(response => { if (!response.ok) { throw new Error(`Server replied HTTP code: ${response.status}`); } return response.blob(); // 応答のタイプを blob に変更します。 }) .then(blob => { const link = document.createElement('a'); link.href = window.URL.createObjectURL(blob); link.download=savePath; // ダウンロードしたオブジェクトの名前を指定します。 document.body.appendChild(link); // このステップにより、署名付き URL がドキュメントに存在することが保証されます。 link.click(); // 署名付き URL をクリックして、オブジェクトのダウンロードをシミュレートします。 link.remove(); // オブジェクトがダウンロードされた後、署名付き URL を削除します。 console.log("Download completed!"); }) .catch(error => { console.error("Error during download:", error); });Android-Java
import android.os.AsyncTask; import android.os.Environment; import java.io.BufferedInputStream; import java.io.FileOutputStream; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; public class DownloadTask extends AsyncTask<String, String, String> { @Override protected String doInBackground(String... params) { String fileURL = params[0]; String savePath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/myfile.txt"; // ダウンロードしたオブジェクトを保存するパスを指定します。 try { URL url = new URL(fileURL); HttpURLConnection httpConn = (HttpURLConnection) url.openConnection(); httpConn.setRequestMethod("GET"); int responseCode = httpConn.getResponseCode(); if (responseCode == HttpURLConnection.HTTP_OK) { InputStream inputStream = new BufferedInputStream(httpConn.getInputStream()); FileOutputStream outputStream = new FileOutputStream(savePath); byte[] buffer = new byte[4096]; int bytesRead; while ((bytesRead = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, bytesRead); } outputStream.close(); inputStream.close(); return "Download completed!"; } else { return "No file to download. Server replied HTTP code: " + responseCode; } } catch (Exception e) { return "Error during download: " + e.getMessage(); } } }Objective-C
#import <Foundation/Foundation.h> int main(int argc, const char * argv[]) { @autoreleasepool { // 署名付き URL とオブジェクトを保存するパスを指定します。 NSString *fileURL = @"https://examplebucket.oss-cn-hangzhou.aliyuncs.com/exampleobject.txt?x-oss-date=20241112T092756Z&x-oss-expires=3599&x-oss-signature-version=OSS4-HMAC-SHA256&x-oss-credential=LTAI****************/20241112/cn-hangzhou/oss/aliyun_v4_request&x-oss-signature=ed5a******************************************************"; NSString *savePath = @"/Users/your_username/Desktop/myfile.txt"; // your_username をユーザー名に置き換えます。 // URL オブジェクトを作成します。 NSURL *url = [NSURL URLWithString:fileURL]; // オブジェクトダウンロードタスクを作成します。 NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { // エラーを処理します。 if (error) { NSLog(@"Error during download: %@", error.localizedDescription); return; } // オブジェクト内のデータを確認します。 if (!data) { NSLog(@"No data received."); return; } // オブジェクトを保存します。 NSError *writeError = nil; BOOL success = [data writeToURL:[NSURL fileURLWithPath:savePath] options:NSDataWritingAtomic error:&writeError]; if (success) { NSLog(@"Download completed!"); } else { NSLog(@"Error saving file: %@", writeError.localizedDescription); } }]; // オブジェクトダウンロードタスクを開始します。 [task resume]; // 非同期リクエストを完了するためにメインスレッドを実行し続けます。 [[NSRunLoop currentRunLoop] run]; } return 0; }
一般的なシナリオ
オブジェクトの特定バージョンに対する HTTP GET リクエストを許可する署名付き URL を生成する
指定されたリクエストヘッダーを含む署名付き URL を使用してオブジェクトをダウンロードする
署名付き URL を使用してオブジェクトを強制的にダウンロードする
カスタムエンドポイントを使用してオブジェクトのダウンロードを許可する署名付き URL を生成する
参考資料
署名付き URL を使用してオブジェクトをダウンロードするための完全なサンプルコードについては、「presigner_get_object.py」をご参照ください。