デフォルトでは、Object Storage Service (OSS) バケット内のオブジェクトは非公開であり、オブジェクト所有者のみがアクセスできます。このトピックでは、OSS PHP SDK を使用して GET リクエストの署名付き URL を生成する方法について説明します。署名付き URL は指定された期間有効で、他のユーザーが一時的にオブジェクトをダウンロードできるようにします。URL は有効期限が切れるまで複数回アクセスできます。URL の有効期限が切れた後は、新しい URL を生成する必要があります。
注意事項
このトピックのサンプルコードでは、中国 (杭州) リージョン ID の
cn-hangzhouを例として使用しています。デフォルトでは、パブリックエンドポイントを使用します。同じリージョン内の他の Alibaba Cloud サービスから OSS にアクセスする場合は、内部エンドポイントを使用します。OSS でサポートされているリージョンとエンドポイントの詳細については、「リージョンとエンドポイント」をご参照ください。このトピックでは、環境変数を使用してアクセス資格情報を取得する例を示します。アクセス資格情報を構成するその他の例については、「PHP のアクセス資格情報を構成する」をご参照ください。
署名付き URL を生成するために特殊なアクセス許可は必要ありません。ただし、
oss:GetObject権限がある場合にのみ、第三者は署名付き URL を使用してオブジェクトを正常にダウンロードできます。権限を付与する方法の詳細については、「RAM ユーザーにカスタムアクセスポリシーを付与する」をご参照ください。このトピックのサンプルコードでは、V4 署名付き URL を使用しています。これは最大 7 日間有効です。詳細については、「署名 V4 (推奨)」をご参照ください。
プロセス
次のフローチャートは、署名付き URL を使用してオブジェクトをダウンロードする方法を示しています。
パラメーター
パラメーター | 必須 | 説明 | 例 |
| はい | バケットが配置されているリージョン。 |
|
| はい | バケット名。 |
|
| はい | パスを含むオブジェクト名。 |
|
| いいえ | 有効期限 (秒単位)。デフォルト: 900。 |
|
| いいえ | エンドポイント。指定しない場合、システムはリージョンに基づいて対応するパブリックエンドポイントを自動的に使用します。 |
|
サンプルコード
オブジェクト所有者が GET リクエストの署名付き URL を生成します。
<?php // 依存ライブラリが正しくロードされるように、オートローダーファイルをインポートします。 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], // オブジェクト名。(必須) "expire" => ['help' => 'The expiration time in seconds (default: 900)', 'required' => False], // 有効期限 (秒単位)。(オプション、デフォルト: 900) ]; // 引数の説明を 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"]; // オブジェクト名。 $expire = isset($options["expire"]) ? (int)$options["expire"] : 900; // 有効期限。デフォルト: 900 秒。 // 環境変数から資格情報をロードします。 // EnvironmentVariableCredentialsProvider を使用して、環境変数から Access Key ID と Access Key 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"]); // エンドポイントが提供されている場合は、それを設定します。 } try { // OSS クライアントインスタンスを作成します。 $client = new Oss\Client($cfg); // オブジェクトをダウンロードするための GetObjectRequest オブジェクトを作成します。 $request = new Oss\Models\GetObjectRequest(bucket:$bucket, key:$key); // presign メソッドを呼び出して署名付き URL を生成し、有効期限を設定します。 $result = $client->presign($request, [ 'expires' => new \DateInterval("PT{$expire}S") // PT は Period Time、S は秒を表します。 ]); // 署名付き URL を出力します。 echo "Signed URL: " . $result->url . PHP_EOL; } catch (Exception $e) { echo "Error: " . $e->getMessage() . PHP_EOL; exit(1); }他のユーザーは、GET リクエストの署名付き 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; }