全部產品
Search
文件中心

Object Storage Service:使用預簽名URL下載(PHP SDK V2)

更新時間:Oct 25, 2025

預設情況下,OSS Bucket中的檔案是私人的,僅檔案擁有者可訪問。本文介紹如何使用OSS PHP SDK產生帶有到期時間的GET方法預簽名URL,以允許他人臨時下載檔案。在有效期間內可多次訪問,超期後需重建。

注意事項

  • 本文範例程式碼以華東1(杭州)的地區IDcn-hangzhou為例,預設使用外網Endpoint,如果您希望通過與OSS同地區的其他阿里雲產品訪問OSS,請使用內網Endpoint。關於OSS支援的Region與Endpoint的對應關係,請參見地區和Endpoint

  • 本文以從環境變數讀取存取憑證為例。更多配置訪問憑證的樣本,請參見PHP配置訪問憑證

  • 預簽名URL無需許可權即可產生,但僅當您擁有oss:GetObject許可權時,第三方才能通過該預簽名URL成功下載檔案。具體授權操作,請參見為RAM使用者授權自訂的權限原則

  • 本文範例程式碼使用V4預簽名URL,有效期間最大為7天。更多資訊,請參見簽名版本4(推薦)

使用過程

使用預簽名URL下載檔案的過程如下:

參數說明

參數

是否必填

說明

樣本

--region

Bucket所在的地區

cn-hangzhou

--bucket

Bucket名稱

examplebucket

--key

檔案名稱(含路徑)

my-object.txt

--expire

到期時間(秒),預設900秒

600

--endpoint

訪問網域名稱,預設會根據region自動使用對應的外網Endpoint。

oss-cn-hangzhou.aliyuncs.com

範例程式碼

  1. 檔案擁有者產生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], // Bucket所在的地區(必填)
        "endpoint" => ['help' => 'The domain names that other services can use to access OSS.', 'required' => False], // 訪問網域名稱(可選)
        "bucket" => ['help' => 'The name of the bucket', 'required' => True], // Bucket名稱(必填)
        "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所在的地區
    $bucket = $options["bucket"]; // 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); // 設定Bucket所在的地區
    if (isset($options["endpoint"])) {
        $cfg->setEndpoint($options["endpoint"]); // 如果提供了訪問網域名稱,則設定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 "預簽名URL: " . $result->url . PHP_EOL;
    } catch (Exception $e) {
        echo "錯誤: " . $e->getMessage() . PHP_EOL;
        exit(1);
    }
  2. 其他人使用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) {
            // 替換為產生的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); // 此步驟確保連結存在於文檔中
            link.click(); // 類比點擊下載連結
            link.remove(); // 完成後移除連結
            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"; // 請替換為您的使用者名稱
            
            // 建立 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;
    }

常見使用情境

產生指定版本的檔案的GET方法的預簽名URL

以下程式碼範例在產生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], // Bucket所在的地區(必填)
    "endpoint" => ['help' => 'The domain names that other services can use to access OSS.', 'required' => False], // 訪問網域名稱(可選)
    "bucket" => ['help' => 'The name of the bucket', 'required' => True], // Bucket名稱(必填)
    "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所在的地區
$bucket = $options["bucket"]; // Bucket名稱
$key = $options["key"];       // 對象名稱

// 載入環境變數中的憑證資訊
// 使用EnvironmentVariableCredentialsProvider從環境變數中讀取Access Key ID和Access Key Secret
$credentialsProvider = new Oss\Credentials\EnvironmentVariableCredentialsProvider();

// 使用SDK的預設配置
$cfg = Oss\Config::loadDefault();
$cfg->setCredentialsProvider($credentialsProvider); // 設定憑證提供者
$cfg->setRegion($region); // 設定Bucket所在的地區
if (isset($options["endpoint"])) {
    $cfg->setEndpoint($options["endpoint"]); // 如果提供了訪問網域名稱,則設定endpoint
}

// 建立OSS用戶端執行個體
$client = new Oss\Client($cfg);

$versionId = "yourVersionId"; // 版本號碼,此處僅為樣本值,實際使用時請替換為真實的版本ID

// 建立GetObjectRequest對象,用於下載對象
$request = new Oss\Models\GetObjectRequest(bucket:$bucket, key:$key, versionId: $versionId);

// 調用presign方法產生預簽名URL
$result = $client->presign($request);

// 列印預簽名結果
// 輸出預簽名URL,使用者可以直接使用該URL進行下載操作
print(
    'get object presign result:' . var_export($result, true) . PHP_EOL . // 預簽名結果的詳細資料
    'get object url:' . $result->url . PHP_EOL                           // 預簽名URL,用於直接下載對象
);

使用預簽名URL下載指定要求標頭的檔案

在產生GET方式的預簽名URL時,如果您指定了要求標頭,確保在通過該預簽名URL發起GET請求時也包含相應的要求標頭,以免出現不一致,導致請求失敗和簽名錯誤。

  1. 產生帶要求標頭的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], // Bucket所在的地區(必填)
        "endpoint" => ['help' => 'The domain names that other services can use to access OSS.', 'required' => False], // 訪問網域名稱(可選)
        "bucket" => ['help' => 'The name of the bucket', 'required' => True], // Bucket名稱(必填)
        "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所在的地區
    $bucket = $options["bucket"]; // Bucket名稱
    $key = $options["key"];       // 對象名稱
    
    // 載入環境變數中的憑證資訊
    // 使用EnvironmentVariableCredentialsProvider從環境變數中讀取Access Key ID和Access Key Secret
    $credentialsProvider = new Oss\Credentials\EnvironmentVariableCredentialsProvider();
    
    // 使用SDK的預設配置
    $cfg = Oss\Config::loadDefault();
    $cfg->setCredentialsProvider($credentialsProvider); // 設定憑證提供者
    $cfg->setRegion($region); // 設定Bucket所在的地區
    if (isset($options["endpoint"])) {
        $cfg->setEndpoint($options["endpoint"]); // 如果提供了訪問網域名稱,則設定endpoint
    }
    
    // 建立OSS用戶端執行個體
    $client = new Oss\Client($cfg);
    
    // 指定rangeBehavior要求標頭,此處設定為'standard'
    $rangeBehavior = 'standard';
    
    // 建立GetObjectRequest對象,用於下載對象
    $request = new Oss\Models\GetObjectRequest(bucket:$bucket, key:$key, rangeBehavior: $rangeBehavior);
    
    // 調用presign方法產生預簽名URL
    $result = $client->presign($request);
    
    // 列印預簽名結果
    // 輸出預簽名URL,使用者可以直接使用該URL進行下載操作
    print(
        'get object presign result:' . var_export($result, true) . PHP_EOL . // 預簽名結果的詳細資料
        'get object url:' . $result->url . PHP_EOL                           // 預簽名URL,用於直接下載對象
    );
    
  2. 使用預簽名URL並指定要求標頭下載檔案。

    curl -X GET "https://examplebucket.oss-cn-hangzhou.aliyuncs.com/exampleobject.txt?x-oss-date=20241113T093321Z&x-oss-expires=3599&x-oss-signature-version=OSS4-HMAC-SHA256&x-oss-credential=LTAI5tKHJzUF3wMmACXgf1aH****************&x-oss-signature=f1746f121783eed5dab2d665da95fbca08505263e27476a46f88dbe3702af8a9***************************************" \
    -H "x-oss-range-behavior: standard" \
    -o "myfile.txt"

使用自訂網域名產生用於下載的預簽名URL

以下程式碼範例使用自訂網域名產生用於下載的預簽名URL。

警告

您需要先將自訂網域名綁定至Bucket預設網域名稱,否則將引發報錯!關於綁定自訂網域名的詳細操作,請參見通過自訂網域名訪問OSS

<?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], // Bucket所在的地區(必填)
    "endpoint" => ['help' => 'The domain names that other services can use to access OSS.', 'required' => False], // 訪問網域名稱(可選)
    "bucket" => ['help' => 'The name of the bucket', 'required' => True], // Bucket名稱(必填)
    "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所在的地區
$bucket = $options["bucket"]; // Bucket名稱
$key = $options["key"];       // 對象名稱

// 載入環境變數中的憑證資訊
// 使用EnvironmentVariableCredentialsProvider從環境變數中讀取Access Key ID和Access Key Secret
$credentialsProvider = new Oss\Credentials\EnvironmentVariableCredentialsProvider();

// 使用SDK的預設配置
$cfg = Oss\Config::loadDefault();
$cfg->setCredentialsProvider($credentialsProvider); // 設定憑證提供者
$cfg->setRegion($region); // 設定Bucket所在的地區
$cfg->setEndpoint(endpoint: "http://static.example.com"); // 請設定為您的自訂endpoint
$cfg->setUseCname(true); // 設定為使用CNAME

// 建立OSS用戶端執行個體
$client = new Oss\Client($cfg);


// 建立GetObjectRequest對象,用於下載對象
$request = new Oss\Models\GetObjectRequest(bucket:$bucket, key:$key);

// 調用presign方法產生預簽名URL
$result = $client->presign($request);

// 列印預簽名結果
// 輸出預簽名URL,使用者可以直接使用該URL進行下載操作
print(
    'get object presign result:' . var_export($result, true) . PHP_EOL . // 預簽名結果的詳細資料
    'get object url:' . $result->url . PHP_EOL                           // 預簽名URL,用於直接下載對象
);

相關文檔

  • 關於預簽名URL的完整範例程式碼,請參見GitHub樣本

  • 關於預簽名URL的API介面,請參見Presign