全部產品
Search
文件中心

Object Storage Service:使用預簽名URL下載或預覽檔案

更新時間:Jul 09, 2025

OSS檔案預設為私人許可權,只有檔案擁有者可訪問。但檔案擁有者可以產生分享連結(預簽名URL),授權他人在有效期間內下載或線上預覽指定檔案。

工作原理

預簽名URL的產生過程依賴祕密金鑰加密和參數拼接,過程如下:

  1. 許可權校正:您產生預簽名URL時需擁有oss:GetObject許可權,第三方才能通過該預簽名URL成功下載/預覽檔案;

  2. 本地加密:基於AK/SK對檔案路徑、到期時間等資訊加密計算,得到簽名(x-oss-signature);

  3. 附加簽名:將簽名參數(x-oss-datex-oss-expiresx-oss-credential 等)作為查詢字串附加到檔案URL;

  4. 形成連結:組成完整的預簽名URL。

    預簽名URL格式

    https://BucketName.Endpoint/Object?簽名參數

    完整樣本

    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*********************************

詳細產生過程請參見簽名版本4(推薦)

擷取檔案的下載連結

使用OSS預設訪問網域名稱組建檔案的帶有效期間的下載連結(預簽名URL)。

使用OSS控制台

您可以登入OSS管理主控台,進入目標Bucket的檔案清單,單擊目標檔案後在右側詳情面板複製檔案URL,即可擷取預設有效期間為32400秒(9小時)的臨時下載連結。

使用阿里雲SDK

以下是常見語言的組建檔案的下載連結(預簽名URL)的程式碼範例。

Java

更多樣本,請參見Java使用預簽名URL下載檔案

import com.aliyun.oss.*;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.common.comm.SignVersion;

import java.net.URL;
import java.util.Date;

public class Demo {
    public static void main(String[] args) throws Throwable {
        // 以華東1(杭州)的外網Endpoint為例,其它Region請按實際情況填寫。
        String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
        // 從環境變數中擷取訪問憑證。運行本程式碼範例之前,請確保已設定環境變數OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
        // 填寫Bucket名稱,例如examplebucket。
        String bucketName = "examplebucket";
        // 填寫Object完整路徑,例如exampleobject.txt。Object完整路徑中不能包含Bucket名稱。
        String objectName = "exampleobject.txt";
        // 填寫Bucket所在地區。以華東1(杭州)為例,Region填寫為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();

        try {
            // 設定預簽名URL到期時間,單位為毫秒。本樣本以設定到期時間為1小時為例。
            Date expiration = new Date(new Date().getTime() + 3600 * 1000L);
            // 產生以GET方法訪問的預簽名URL。本樣本沒有額外要求標頭,其他人可以直接通過瀏覽器訪問相關內容。
            URL url = ossClient.generatePresignedUrl(bucketName, objectName, expiration);
            System.out.println(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());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }
}

Python

更多樣本,請參見Python使用預簽名URL下載檔案

import argparse
import alibabacloud_oss_v2 as oss

# 建立一個命令列參數解析器,並描述指令碼用途:產生GET方法的預簽名URL請求樣本
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,表示其他服務可用來訪問OSS的網域名稱,非必需參數
parser.add_argument('--endpoint', help='The domain names that other services can use to access OSS')
# 添加命令列參數 --key,表示對象(檔案)在OSS中的鍵名,必需參數
parser.add_argument('--key', help='The name of the object.', required=True)

def main():
    # 解析命令列提供的參數,擷取使用者輸入的值
    args = parser.parse_args()

    # 從環境變數中載入訪問OSS所需的認證資訊,用於身分識別驗證
    credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider()

    # 使用SDK的預設配置建立設定物件,並設定認證提供者
    cfg = oss.config.load_default()
    cfg.credentials_provider = credentials_provider
    
    # 設定設定物件的地區屬性,根據使用者提供的命令列參數
    cfg.region = args.region

    # 如果提供了自訂endpoint,則更新設定物件中的endpoint屬性
    if args.endpoint is not None:
        cfg.endpoint = args.endpoint

    # 使用上述配置初始化OSS用戶端,準備與OSS互動
    client = oss.Client(cfg)

    # 產生預簽名的GET請求
    pre_result = client.presign(
        oss.GetObjectRequest(
            bucket=args.bucket,  # 指定儲存空間名稱
            key=args.key,        # 指定對象鍵名
        )
    )

    # 列印預簽章要求的方法、到期時間和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()  # 指令碼進入點,控製程序流程從這裡開始

Go

更多樣本,請參見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(&region, "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()

	// 檢查bucket名稱是否為空白
	if len(bucketName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, bucket name required")
	}

	// 檢查region是否為空白
	if len(region) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, region required")
	}

	// 檢查object名稱是否為空白
	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)

	// 產生GetObject的預簽名URL
	result, err := client.Presign(context.TODO(), &oss.GetObjectRequest{
		Bucket: oss.Ptr(bucketName),
		Key:    oss.Ptr(objectName),
	},
		oss.PresignExpires(10*time.Minute),
	)
	if err != nil {
		log.Fatalf("failed to get 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 {
		//當返回結果包含簽名頭時,使用預簽名URL發送GET請求時也包含相應的要求標頭,以免出現不一致,導致請求失敗和預簽名錯誤
		log.Printf("signed headers:\n")
		for k, v := range result.SignedHeaders {
			log.Printf("%v: %v\n", k, v)
		}
	}
}

Node.js

更多樣本,請參見Node.js使用預簽名URL下載檔案

const OSS = require("ali-oss");

// 定義一個產生預簽名 URL 的函數
async function generateSignatureUrl(fileName) {
  // 擷取預簽名URL
  const client = await new OSS({
      // 從環境變數中擷取訪問憑證。運行本程式碼範例之前,請確保已設定環境變數OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
      accessKeyId: process.env.OSS_ACCESS_KEY_ID,
      accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET,
      bucket: 'examplebucket',
      // yourregion填寫Bucket所在地區。以華東1(杭州)為例,Region填寫為oss-cn-hangzhou。
      region: 'oss-cn-hangzhou',
      // 設定secure為true,使用HTTPS,避免產生的下載連結被瀏覽器攔截
      secure: true,
      authorizationV4: true
  });

  return await client.signatureUrlV4('GET', 3600, {
      headers: {} // 請根據實際發送的要求標頭設定此處的要求標頭
  }, fileName);
}
// 調用函數並傳入檔案名稱
generateSignatureUrl('yourFileName').then(url => {
  console.log('Generated Signature URL:', url);
}).catch(err => {
  console.error('Error generating signature URL:', err);
});

PHP

更多樣本,請參見PHP使用預簽名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);

// 建立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,用於直接下載對象
);

.NET

更多樣本,請參見.NET使用預簽名URL下載檔案

using Aliyun.OSS;
using Aliyun.OSS.Common;
// 填寫Bucket所在地區對應的Endpoint。以華東1(杭州)為例,Endpoint填寫為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");
// 填寫Bucket名稱,例如examplebucket。
var bucketName = "examplebucket";
// 填寫Object完整路徑,完整路徑中不包含Bucket名稱,例如exampledir/exampleobject.txt。
var objectName = "exampledir/exampleobject.txt";
// 填寫Bucket所在地區對應的Region。以華東1(杭州)為例,Region填寫為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
{
    var metadata = client.GetObjectMetadata(bucketName, objectName);
    var etag = metadata.ETag;
    // 產生預簽名URL。
    var req = new GeneratePresignedUriRequest(bucketName, objectName, SignHttpMethod.Get)
      {
        // 設定預簽名URL到期時間,預設值為3600秒。
        Expiration = DateTime.UtcNow.AddHours(1),
    };
    var uri = client.GeneratePresignedUri(req);
    // 列印產生的預簽名URL
    Console.WriteLine("Generated Signed URL: " + uri);
}
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);
}

Android

更多SDK資訊,請參見Android使用預簽名URL下載檔案

// 填寫Bucket名稱,例如examplebucket。
String bucketName = "examplebucket";
// 填寫不包含Bucket名稱在內源Object的完整路徑,例如exampleobject.txt。
String objectKey = "exampleobject.txt";
String url = null;
try {
    // 產生用於下載檔案的預簽名URL。
    GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucketName, objectKey);
    // 設定預簽名URL的到期時間為30分鐘。
    request.setExpiration(30*60);
    request.setMethod(HttpMethod.GET);
    url = oss.presignConstrainedObjectURL(request);
    Log.d("url", url);
} catch (ClientException e) {
    e.printStackTrace();
}

iOS

更多SDK資訊,請參見iOS使用預簽名URL下載檔案

// 填寫Bucket名稱。
NSString *bucketName = @"examplebucket";
// 填寫Object名稱。
NSString *objectKey = @"exampleobject.txt";
__block NSString *urlString;
// 產生用於下載的預簽名URL,並指定預簽名URL到期時間為30分鐘。
OSSTask *task = [client presignConstrainURLWithBucketName:bucketName
                                            withObjectKey:objectKey
                                               httpMethod:@"GET"
                                   withExpirationInterval:30 * 60
                                           withParameters:@{}];
[task continueWithBlock:^id _Nullable(OSSTask * _Nonnull task) {
    if (task.error) {
        NSLog(@"presign error: %@", task.error);
    } else {
        urlString = task.result;
        NSLog(@"url: %@", urlString);
    }
    return nil;
}];

C++

更多SDK資訊,請參見C++使用預簽名URL下載檔案

#include <alibabacloud/oss/OssClient.h>
using namespace AlibabaCloud::OSS;

int main(void)
{
    /* 初始化OSS帳號資訊。*/
            
    /* yourEndpoint填寫Bucket所在地區對應的Endpoint。以華東1(杭州)為例,Endpoint填寫為https://oss-cn-hangzhou.aliyuncs.com。*/
    std::string Endpoint = "yourEndpoint";
    /* yourRegion填寫Bucket所在地區對應的Region。以華東1(杭州)為例,Region填寫為cn-hangzhou。*/
    std::string Region = "yourRegion";
    /* 填寫Bucket名稱,例如examplebucket。*/
    std::string BucketName = "examplebucket";
    /* 填寫Object完整路徑,完整路徑中不能包含Bucket名稱,例如exampledir/exampleobject.txt。*/ 
    std::string GetobjectUrlName = "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);

    /* 設定簽名有效時間長度,最大有效時間為32400秒。*/
    std::time_t t = std::time(nullptr) + 1200;
    /* 產生預簽名URL。*/
    auto genOutcome = client.GeneratePresignedUrl(BucketName, GetobjectUrlName, t, Http::Get);
    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;
}

Ruby

更多SDK資訊,請參見Ruby使用預簽名URL下載檔案

require 'aliyun/oss'

client = Aliyun::OSS::Client.new(
  # Endpoint以華東1(杭州)為例,其它Region請按實際情況填寫。
  endpoint: 'https://oss-cn-hangzhou.aliyuncs.com',
  # 從環境變數中擷取訪問憑證。運行本程式碼範例之前,請確保已設定環境變數OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
  access_key_id: ENV['OSS_ACCESS_KEY_ID'],
  access_key_secret: ENV['OSS_ACCESS_KEY_SECRET']
)
# 填寫Bucket名稱,例如examplebucket。
bucket = client.get_bucket('examplebucket')

# 產生預簽名URL,並指定URL有效時間為1小時(3600秒)。
puts bucket.object_url('my-object', true, 3600)

C

更多SDK資訊,請參見C使用預簽名URL下載檔案

#include "oss_api.h"
#include "aos_http_io.h"
/* yourEndpoint填寫Bucket所在地區對應的Endpoint。以華東1(杭州)為例,Endpoint填寫為https://oss-cn-hangzhou.aliyuncs.com。*/
const char *endpoint = "yourEndpoint";
/* 填寫Bucket名稱,例如examplebucket。*/
const char *bucket_name = "examplebucket";
/* 填寫Object完整路徑,完整路徑中不能包含Bucket名稱,例如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);
    /* 用char*類型的字串初始化aos_string_t類型。*/
    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表示不使用。*/
    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;
    /* 重新建立一個記憶體池,第二個參數是NULL,表示沒有繼承其它記憶體池。*/
    aos_pool_create(&pool, NULL);
    /* 建立並初始化options,該參數包括endpoint、access_key_id、acces_key_secret、is_cname、curl等全域配置資訊。*/
    oss_request_options_t *oss_client_options;
    /* 在記憶體池中分配記憶體給options。*/
    oss_client_options = oss_request_options_create(pool);
    /* 初始化Client的選項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_GET;
    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("臨時下載URL: %s\n", url_str);     
    /* 釋放記憶體池,相當於釋放了請求過程中各資源分派的記憶體。*/
    aos_pool_destroy(pool);
    /* 釋放之前分配的全域資源。*/
    aos_http_io_deinitialize();
    return 0;
}

產生的預簽名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*********************************************

使用命令列工具ossutil

對儲存空間examplebucket裡的example.txt對象,產生預設有效期間為15分鐘的檔案的下載連結(預簽名URL),命令如下。

ossutil presign oss://examplebucket/example.txt

關於使用ossutil產生預簽名URL的更多樣本, 請參見presign(產生預簽名URL)

使用圖形化管理工具ossbrowser

ossbrowser支援Object層級的操作與控制台支援的操作類似,請按照ossbrowser介面指引完成擷取預簽名URL的操作。關於如何使用ossbrowser,請參見常用操作

擷取檔案的線上預覽連結

若要產生支援線上預覽的連結(預簽名 URL),需先綁定自訂網域名。綁定完成後,使用自訂網域名產生預簽名URL。

使用OSS控制台

  1. 登入OSS管理主控台

  2. 單擊Bucket列表,然後單擊目標Bucket名稱。

  3. 在左側導覽列,選擇文件管理 > 檔案清單

  4. 在檔案清單頁面,單擊目標檔案名稱。

  5. 詳情面板的自有網域名稱,選擇綁定的自訂網域名,其他保持預設值,然後單擊複製檔案URL

    image

使用圖形化管理工具ossbrowser

ossbrowser支援Object層級的操作與控制台支援的操作類似,請按照ossbrowser介面指引完成擷取預簽名URL的操作。如何下載ossbrowser,請參見圖形化管理工具ossbrowser 2.0(預覽版)

  1. 使用自訂網域名登入ossbrowser。

  1. 擷取檔案URL。

使用阿里雲SDK

使用自訂網域名建立OssClient並產生預簽名URL。

Java

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.Date;

public class Demo {
    public static void main(String[] args) throws Throwable {
        // yourCustomEndpoint請填寫您的自訂網域名。例如http://static.example.com。
        String endpoint = "yourCustomEndpoint";
        // 請填寫您儲存空間所在的Region資訊,例如cn-hangzhou
        String region = "cn-hangzhou";
        // 填寫Bucket名稱,例如examplebucket。
        String bucketName = "examplebucket";
        // 填寫Object完整路徑,例如exampleobject.txt。Object完整路徑中不能包含Bucket名稱。
        String objectName = "exampleobject.txt";

        // 從環境變數中擷取訪問憑證。運行本程式碼範例之前,請先配置環境變數
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();

        // 建立OSSClient執行個體。
        // 當OSSClient執行個體不再使用時,調用shutdown方法以釋放資源。
        ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
        // 請注意,設定true開啟CNAME選項
        clientBuilderConfiguration.setSupportCname(true);
        // 顯式聲明使用 V4 簽名演算法
        clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);
        OSS ossClient = OSSClientBuilder.create()
                .endpoint(endpoint)
                .credentialsProvider(credentialsProvider)
                .clientConfiguration(clientBuilderConfiguration)
                .region(region)
                .build();

        try {
            // 指定產生的預簽名URL到期時間,單位為毫秒。本樣本以設定到期時間為1小時為例。
            Date expiration = new Date(new Date().getTime() + 3600 * 1000L);

            // 產生預簽名URL。
            GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucketName, objectName, HttpMethod.GET);

            // 設定到期時間。
            request.setExpiration(expiration);

            // 通過HTTP GET請求產生預簽名URL。
            URL signedUrl = ossClient.generatePresignedUrl(request);
            // 列印預簽名URL。
            System.out.println("signed url for getObject: " + 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());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }
}

PHP

<?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,用於直接下載對象
);

Node.js

const OSS = require("ali-oss");

// 定義一個產生預簽名 URL 的函數
async function generateSignatureUrl(fileName) {
  // 擷取預簽名URL
  const client = await new OSS({
      // 使用自訂網域名作為Endpoint。
      endpoint: 'http://static.example.com', 
      // 從環境變數中擷取訪問憑證。運行本程式碼範例之前,請確保已設定環境變數OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
      accessKeyId: process.env.OSS_ACCESS_KEY_ID,
      accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET,
      bucket: 'examplebucket',
      // yourregion填寫Bucket所在地區。以華東1(杭州)為例,Region填寫為oss-cn-hangzhou。
      region: 'oss-cn-hangzhou',
      authorizationV4: true,
      cname: true
  });

  return await client.signatureUrlV4('GET', 3600, {
      headers: {} // 請根據實際發送的要求標頭設定此處的要求標頭
  }, fileName);
}
// 調用函數並傳入檔案名稱
generateSignatureUrl('yourFileName').then(url => {
  console.log('Generated Signature URL:', url);
}).catch(err => {
  console.error('Error generating signature URL:', err);
});

Python

import argparse
import alibabacloud_oss_v2 as oss

# 建立一個命令列參數解析器,並描述指令碼用途:產生預簽名GET請求樣本
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,表示其他服務可用來訪問OSS的網域名稱,非必需參數
parser.add_argument('--endpoint', help='The domain names that other services can use to access OSS')
# 添加命令列參數 --key,表示對象(檔案)在OSS中的鍵名,必需參數
parser.add_argument('--key', help='The name of the object.', required=True)

def main():
    # 解析命令列提供的參數,擷取使用者輸入的值
    args = parser.parse_args()

    # 從環境變數中載入訪問OSS所需的認證資訊,用於身分識別驗證
    credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider()

    # 使用SDK的預設配置建立設定物件,並設定認證提供者
    cfg = oss.config.load_default()
    cfg.credentials_provider = credentials_provider
    
    # 設定設定物件的地區屬性,根據使用者提供的命令列參數
    cfg.region = args.region

    # 設定自訂網域名,例如“http://static.example.com”
    cfg.endpoint = "http://static.example.com"
    
    # 設定使用CNAME
    cfg.use_cname = True

    # 使用上述配置初始化OSS用戶端,準備與OSS互動
    client = oss.Client(cfg)

    # 產生預簽名的GET請求
    pre_result = client.presign(
        oss.GetObjectRequest(
            bucket=args.bucket,  # 指定儲存空間名稱
            key=args.key,        # 指定對象鍵名
        )
    )

    # 列印預簽章要求的方法、到期時間和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()  # 指令碼進入點,控製程序流程從這裡開始

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(&region, "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()

	// 檢查bucket名稱是否為空白
	if len(bucketName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, bucket name required")
	}

	// 檢查region是否為空白
	if len(region) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, region required")
	}

	// 檢查object名稱是否為空白
	if len(objectName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, object name required")
	}

	// 載入預設配置並設定憑證提供者和地區
	cfg := oss.LoadDefaultConfig().
		WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()).
		WithRegion(region).
		WithEndpoint("http://static.example.com").
		WithUseCName(true)

	// 建立OSS用戶端
	client := oss.NewClient(cfg)

	// 產生GetObject的預簽名URL
	result, err := client.Presign(context.TODO(), &oss.GetObjectRequest{
		Bucket: oss.Ptr(bucketName),
		Key:    oss.Ptr(objectName),
		//RequestPayer: oss.Ptr("requester"), // 指定要求者身份
	},
		oss.PresignExpires(10*time.Minute),
	)
	if err != nil {
		log.Fatalf("failed to get 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 {
		//當返回結果包含預簽名頭時,使用預簽名URL發送GET請求時也包含相應的要求標頭,以免出現不一致,導致請求失敗和預簽名錯誤
		log.Printf("signed headers:\n")
		for k, v := range result.SignedHeaders {
			log.Printf("%v: %v\n", k, v)
		}
	}
}

使用命令列工具ossutil

使用自訂網域名通過presign(產生預預簽名URL)命令組建檔案的預簽名URL。

ossutil presign oss://examplebucket/exampleobject.txt --endpoint "http://static.example.com” --addressing-style "cname"

如需ossutil命令自動使用自訂網域名,而無需每次在命令中手動指定自訂網域名,您可以在設定檔中添加自訂網域名,

如果連結仍無法預覽,還需檢查以下配置。

  • Content-Type設定是否合理?

    如果檔案的Content-Type與實際類型不一致,瀏覽器可能無法正確識別並渲染內容,從而將檔案作為附件下載。您可以對照如何設定Content-Type(MIME)?確認副檔名與Content-Type是否匹配。如不一致,請參考管理檔案中繼資料中的方法修改檔案的Content-Type

  • Content-Disposition是否為inline

    如果檔案的Content-Disposition被設定為attachment,瀏覽器會強制下載檔案。請參考管理檔案中繼資料中的方法其修改為inline以支援預覽。

  • 是否重新整理CDN緩衝?

    如果您未使用CDN加速,可忽略本項。

    如果您使用CDN訪問OSS資源,修改檔案中繼資料後需重新整理 CDN 緩衝,否則仍可能讀取舊配置,導致預覽不生效。

擷取檔案的強制下載連結

如果當前連結(預簽名URL)在瀏覽器中開啟會直接預覽,但您希望改為下載效果,可使用以下方法。方式一優先順序高於方式二。

方式一:單次強制下載

僅對當前產生的連結生效。通過在產生 URL 時設定response-content-disposition參數為attachment實現。

Java

匯入GeneratePresignedUrlRequest類。

import com.aliyun.oss.model.GeneratePresignedUrlRequest;

使用 GeneratePresignedUrlRequest方法,並設定response-content-disposition回應標頭為attachment

// 構建 GET 請求的預簽名 URL
GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(
    bucketName, objectName, HttpMethod.GET);

// 設定強制下載
request.getResponseHeaders().setContentDisposition("attachment");

Python

GetObjectRequest中添加response_content_disposition參數,並設定值為attachment

    # 產生預簽名的GET請求
    pre_result = client.presign(
        oss.GetObjectRequest(
            bucket=args.bucket,  # 指定儲存空間名稱
            key=args.key,        # 指定對象鍵名
            response_content_disposition="attachment",# 設定為強制下載
        )
    )

Go

GetObjectRequest中添加ResponseContentDisposition參數,並設定值為attachment

// 產生帶有強制下載行為的預簽名 GET 請求
result, err := client.Presign(context.TODO(), &oss.GetObjectRequest{
    Bucket:                     oss.Ptr(bucketName),
    Key:                        oss.Ptr(objectName),
    ResponseContentDisposition: oss.Ptr("attachment"), // 設定為強制下載
})

完整範例程式碼

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.model.GeneratePresignedUrlRequest;

import java.net.URL;
import java.net.URLEncoder;
import java.util.Date;

public class Demo {
    public static void main(String[] args) throws Throwable {
        // 請填寫您的自訂網域名。例如http://static.example.com。
        String endpoint = "http://static.example.com";
        // 從環境變數中擷取訪問憑證。運行本程式碼範例之前,請確保已設定環境變數OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();

        // 填寫Bucket名稱,例如examplebucket。
        String bucketName = "examplebucket";
        // 填寫Object完整路徑,例如exampleobject.txt。Object完整路徑中不能包含Bucket名稱。
        String objectName = "exampleobject.txt";

        // 建立OSSClient執行個體。
        // 當OSSClient執行個體不再使用時,調用shutdown方法以釋放資源。
        String region = "cn-hangzhou";
        ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
        // 請注意,若您使用自訂網域名,需設定CNAME為true。
        clientBuilderConfiguration.setSupportCname(true);

        //設定V4簽名演算法
        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);

            // 定義用戶端下載時顯示的檔案名稱,此處以"homework.txt"為例。
            String filename = "homework.txt";

            // 產生預簽名URL。
            GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucketName, objectName, HttpMethod.GET);

            // 設定下載行為(強制下載而非預覽)及檔案名稱
            request.getResponseHeaders().setContentDisposition("attachment;filename=" + URLEncoder.encode(filename,"UTF-8"));

            // 設定到期時間。
            request.setExpiration(expiration);

            // 通過HTTP GET請求產生預簽名URL。
            signedUrl = ossClient.generatePresignedUrl(request);
            // 列印預簽名URL。
            System.out.println("signed url for getObject: " + 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());
        }
    }

}

Python

import argparse
import alibabacloud_oss_v2 as oss

# 建立一個命令列參數解析器,並描述指令碼用途:產生GET方法的預簽名URL請求樣本
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,表示其他服務可用來訪問OSS的網域名稱,非必需參數
parser.add_argument('--endpoint', help='The domain names that other services can use to access OSS')
# 添加命令列參數 --key,表示對象(檔案)在OSS中的鍵名,必需參數
parser.add_argument('--key', help='The name of the object.', required=True)

def main():
    # 解析命令列提供的參數,擷取使用者輸入的值
    args = parser.parse_args()

    # 從環境變數中載入訪問OSS所需的認證資訊,用於身分識別驗證
    credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider()

    # 使用SDK的預設配置建立設定物件,並設定認證提供者
    cfg = oss.config.load_default()
    cfg.credentials_provider = credentials_provider

    # 設定設定物件的地區屬性,根據使用者提供的命令列參數
    cfg.region = args.region

    # 如果提供了自訂endpoint,則更新設定物件中的endpoint屬性
    if args.endpoint is not None:
        cfg.endpoint = args.endpoint

    # 使用上述配置初始化OSS用戶端,準備與OSS互動
    client = oss.Client(cfg)

    # 產生預簽名的GET請求
    pre_result = client.presign(
        oss.GetObjectRequest(
            bucket=args.bucket,  # 指定儲存空間名稱
            key=args.key,        # 指定對象鍵名
            response_content_disposition="attachment;filename=test.txt",
        )
    )

    # 列印預簽章要求的方法、到期時間和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()  # 指令碼進入點,控製程序流程從這裡開始

Go

package main

import (
	"context"
	"flag"
	"log"

	"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(&region, "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()

	// 檢查bucket名稱是否為空白
	if len(bucketName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, bucket name required")
	}

	// 檢查region是否為空白
	if len(region) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, region required")
	}

	// 檢查object名稱是否為空白
	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)

	// 產生GetObject的預簽名URL
	result, err := client.Presign(context.TODO(), &oss.GetObjectRequest{
		Bucket:                     oss.Ptr(bucketName),
		Key:                        oss.Ptr(objectName),
		ResponseContentDisposition: oss.Ptr("attachment;filename=test.txt"),
	},
	)
	if err != nil {
		log.Fatalf("failed to get 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 {
		//當返回結果包含簽名頭時,使用簽名URL發送GET請求時,需要設定相應的要求標頭
		log.Printf("signed headers:\n")
		for k, v := range result.SignedHeaders {
			log.Printf("%v: %v\n", k, v)
		}
	}
}

方式二:統一設定強制下載(通過中繼資料)

一次設定後,該檔案的所有訪問都會強制下載。通過修改檔案中繼資料中的Content-Disposition欄位實現。

使用OSS控制台

OSS管理主控台中,找到目標檔案,在該檔案詳情面板中單擊設定檔案中繼資料,將Content-Disposition設定為attachment,然後單擊確定儲存。

除控制台操作外,也可參考管理檔案中繼資料,通過SDK或命令列工具 ossutil 設定該欄位。

如您還希望自訂下載時顯示的檔案名稱,請參見自訂下載時的檔案名稱

擷取指定版本檔案的連結

產生指定版本檔案的連結(預簽名URL),適用於已啟用版本控制的Bucket。

使用OSS控制台

  1. 您可以登入OSS管理主控台,進入目標Bucket的檔案清單,在頁面右上方切換歷史版本顯示

    image

  2. 找到目標檔案,單擊所需歷史版本的檔案名稱,在詳情頁面中即可複製該版本檔案的URL。

    image

使用阿里雲SDK

Java

增加以下關鍵代碼:

// 1. 定義版本ID變數
String versionId = "CAEQARiBgID8rumR2hYiIGUyOTAyZGY2MzU5MjQ5ZjlhYzQzZjNlYTAyZDE3****";

// 2. 建立查詢參數Map
Map<String, String> queryParam = new HashMap<String, String>();
queryParam.put("versionId", versionId);

// 3. 將版本ID參數添加到請求中
request.setQueryParameter(queryParam);

Python

GetObjectRequest中添加version_id參數。

pre_result = client.presign(
    oss.GetObjectRequest(
        bucket=bucket_name,
        key=object_name,
        version_id='CAEQARiBgID8rumR2hYiIGUyOTAyZGY2MzU5MjQ5ZjlhYzQzZjNlYTAyZDE3****'  # 設定VersionId參數 
    )
)

Go

GetObjectRequest中添加VersionId欄位。

result, err := client.Presign(context.TODO(), &oss.GetObjectRequest{
    Bucket:    oss.Ptr(bucketName),
    Key:       oss.Ptr(objectName),
    VersionId: oss.Ptr("CAEQARiBgID8rumR2hYiIGUyOTAyZGY2MzU5MjQ5ZjlhYzQzZjNlYTAyZDE7****"), // 設定VersionId
}, oss.PresignExpires(10*time.Minute))

Node.js

signatureUrlV4中添加queries參數。

const signedUrl = await client.signatureUrlV4('GET', 3600, {
  queries: {
    "versionId": 'CAEQARiBgID8rumR2hYiIGUyOTAyZGY2MzU5MjQ5ZjlhYzQzZjNlYTAyZDE7****'  // 新增versionId參數
  }
}, objectName);

PHP

GetObjectRequest中添加versionId參數。

// 新增指定版本參數
$versionId = "yourVersionId"; // 替換為實際版本號碼
$request = new Oss\Models\GetObjectRequest(bucket:$bucket, key:$key, versionId:$versionId);

完整範例程式碼

Java

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 Demo {
    public static void main(String[] args) throws Throwable {
        // 以華東1(杭州)的外網Endpoint為例,其它Region請按實際情況填寫。
        String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
        // 從環境變數中擷取訪問憑證。運行本程式碼範例之前,請確保已設定環境變數OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
	// 填寫Bucket名稱,例如examplebucket。
        String bucketName = "examplebucket";
        // 填寫Object完整路徑,例如exampleobject.txt。Object完整路徑中不能包含Bucket名稱。
        String objectName = "exampleobject.txt";
        // 填寫Object的versionId。
        String versionId = "CAEQARiBgID8rumR2hYiIGUyOTAyZGY2MzU5MjQ5ZjlhYzQzZjNlYTAyZDE3****";
        // 填寫Bucket所在地區。以華東1(杭州)為例,Region填寫為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();

        try {
            // 建立請求。
            GeneratePresignedUrlRequest generatePresignedUrlRequest = new GeneratePresignedUrlRequest(bucketName, objectName);
            // 設定HttpMethod為GET。
            generatePresignedUrlRequest.setMethod(HttpMethod.GET);
            // 設定預簽名URL到期時間,單位為毫秒。本樣本以設定到期時間為1小時為例。
            Date expiration = new Date(new Date().getTime() + 3600 * 1000L);
            generatePresignedUrlRequest.setExpiration(expiration);
            // Object的versionId。
            Map<String, String> queryParam = new HashMap<String, String>();
            queryParam.put("versionId", versionId);
            generatePresignedUrlRequest.setQueryParameter(queryParam);
            // 產生預簽名URL。
            URL url = ossClient.generatePresignedUrl(generatePresignedUrlRequest);
            System.out.println(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());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }
}

Python

import argparse
import alibabacloud_oss_v2 as oss

# 建立一個命令列參數解析器,並描述指令碼用途:產生GET方法的預簽名URL請求樣本
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,表示其他服務可用來訪問OSS的網域名稱,非必需參數
parser.add_argument('--endpoint', help='The domain names that other services can use to access OSS')
# 添加命令列參數 --key,表示對象(檔案)在OSS中的鍵名,必需參數
parser.add_argument('--key', help='The name of the object.', required=True)

def main():
    # 解析命令列提供的參數,擷取使用者輸入的值
    args = parser.parse_args()

    # 從環境變數中載入訪問OSS所需的認證資訊,用於身分識別驗證
    credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider()

    # 使用SDK的預設配置建立設定物件,並設定認證提供者
    cfg = oss.config.load_default()
    cfg.credentials_provider = credentials_provider
    
    # 設定設定物件的地區屬性,根據使用者提供的命令列參數
    cfg.region = args.region

    # 如果提供了自訂endpoint,則更新設定物件中的endpoint屬性
    if args.endpoint is not None:
        cfg.endpoint = args.endpoint

    # 使用上述配置初始化OSS用戶端,準備與OSS互動
    client = oss.Client(cfg)

    # 產生預簽名的GET請求
    # 注意:version_id 參數是可選的,僅當您的儲存桶啟用了版本控制時才需要使用
    pre_result = client.presign(
        oss.GetObjectRequest(
            bucket=args.bucket,  # 指定儲存空間名稱
            key=args.key,        # 指定對象鍵名
            version_id='yourVersionId'  # 替換為實際的版本ID,如果適用
        )
    )

    # 列印預簽章要求的方法、到期時間和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()  # 指令碼進入點,控製程序流程從這裡開始

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(&region, "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()

	// 檢查bucket名稱是否為空白
	if len(bucketName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, bucket name required")
	}

	// 檢查region是否為空白
	if len(region) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, region required")
	}

	// 檢查object名稱是否為空白
	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)

	// 產生GetObject的預簽名URL
	result, err := client.Presign(context.TODO(), &oss.GetObjectRequest{
		Bucket:    oss.Ptr(bucketName),
		Key:       oss.Ptr(objectName),
		VersionId: oss.Ptr("yourVersionId"), // 指定版本ID
	},
		oss.PresignExpires(10*time.Minute),
	)
	if err != nil {
		log.Fatalf("failed to get object presign %v", err)
	}
	log.Printf("get object presign result: %#v\n", result)
	log.Printf("get object url: %#v\n", result.URL)
}

Node.js

const OSS = require("ali-oss");

const client = await new OSS({
  // 從環境變數中擷取訪問憑證。運行本程式碼範例之前,請確保已設定環境變數OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
  accessKeyId: process.env.OSS_ACCESS_KEY_ID,
  accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET,
  bucket: 'examplebucket',
  // yourregion填寫Bucket所在地區。以華東1(杭州)為例,Region填寫為oss-cn-hangzhou。
  region: 'oss-cn-hangzhou',
  // 設定secure為true,使用HTTPS,避免產生的下載連結被瀏覽器攔截
  secure: true,
  authorizationV4: true
});


// 產生預簽名的URL
const signedUrl = await client.signatureUrlV4('GET', 3600, {
  queries:{
    // 填寫 Object 的 versionId
    "versionId":'yourVersionId'
  }
}, 'demo.pdf');

PHP

<?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,用於直接下載對象
);

使用ossutil

對儲存空間examplebucket裡的example.txt對象,產生版本標識為123的預簽名URL。

ossutil presign oss://examplebucket/example.txt --version-id 123

批量擷取檔案的連結

推薦使用命令列工具ossutil,可為整個目錄下的檔案批量產生連結。

使用命令列工具ossutil

  • 對儲存空間examplebucke內folder目錄下所有檔案,批量產生預設有效期間為15分鐘的預簽名URL。

    ossutil presign oss://examplebucket/folder/ -r
  • 對儲存空間examplebucket裡的folder目錄下的尾碼為.txt的檔案,批量產生預設有效期間為15分鐘的預簽名URL。

    ossutil presign oss://examplebucket/folder/ -r --include "*.txt"
  • 對儲存空間examplebucket下所有檔案,批量產生預設有效期間為15分鐘的預簽名URL。

    ossutil presign oss://examplebucket/ -r

關於使用ossutil產生預簽名URL的更多用法, 請參見presign(產生預簽名URL)

使用OSS控制台

僅支援匯出目前的目錄下檔案的預簽名URL,無法匯出子目錄中的檔案的預簽名URL。

  1. 選中目標檔案,然後單擊下方的匯出URL列表list

  2. 在彈出的配置面板中,預設參數適用於大多數情境,無需修改即可使用。

    參數說明(可選)

    參數

    說明

    使用HTTPS

    預設使用HTTPS協議組建檔案URL。如需使用HTTP協議組建檔案URL,請關閉使用HTTPS開關。

    到期時間

    當目標檔案為私人檔案時,需設定檔案URL的有效時間。

    取值範圍:60~32400

    單位:秒

    自有域名

    如需確保第三方訪問圖片或網頁檔案時是預覽行為,請使用Bucket綁定的自訂網域名產生簽名URL。

    僅當Bucket綁定自訂網域名後可配置此項。

    傳輸加速網域名稱

    若第三方涉及跨國或跨洋等超遠距離檔案訪問情境時,建議使用傳輸加速網域名稱產生URL。

    僅當Bucket開啟傳輸加速後可配置此項。

  3. 單擊確定,下載並儲存產生的URL列表檔案。

使用阿里雲SDK

使用GetBucket (ListObjects)介面擷取所有Object名稱,然後逐個產生預簽名URL。

自訂下載檔案名稱

在強制下載的基礎上,您可以進一步指定使用者儲存檔案時看到的檔案名稱。方式一優先順序高於方式二。

方式一:單次設定下載檔案名稱

為單個預簽名URL指定下載檔案名稱。只需在設定response-content-disposition參數為attachment的基礎上增加filename參數。

Java

設定response-content-disposition參數。

// 設定用戶端下載時顯示的檔案名稱,此處以 "test.txt" 為例
String filename = "test.txt";
request.getResponseHeaders().setContentDisposition("attachment;filename=" + URLEncoder.encode(filename,"UTF-8"));

Python

通過response_content_disposition參數,實現自訂下載檔案名稱為test.txt

    # 產生預簽名的GET請求
    pre_result = client.presign(
        oss.GetObjectRequest(
            bucket=args.bucket,  # 指定儲存空間名稱
            key=args.key,        # 指定對象鍵名
            response_content_disposition="attachment;filename=test.txt",# 設定用戶端下載時顯示的檔案名稱,此處為 "test.txt"
        )
    )

Go

通過ResponseContentDisposition參數,實現自訂下載檔案名稱為test.txt

// 產生帶有強制下載行為的預簽名 GET 請求
result, err := client.Presign(context.TODO(), &oss.GetObjectRequest{
    Bucket:                     oss.Ptr(bucketName),
    Key:                        oss.Ptr(objectName),
    ResponseContentDisposition: oss.Ptr("attachment;filename=test.txt"),//設定用戶端下載時顯示的檔案名稱,此處為 "test.txt"
})

方式二:統一設定(通過中繼資料)

修改中繼資料,為所有訪問設定一個統一的預設下載名。通過修改檔案中繼資料中的Content-Disposition欄位為attachment; filename="yourFileName"實現,yourFileName為自訂的檔案名稱,例如example.jpg

設定連結的有效時間

連結(預簽名URL)的有效期間在產生時設定,過後無法修改。連結在有效期間內可多次訪問,到期後失效。

不同產生方式支援的最大有效期間不同,超出上限會導致產生失敗或訪問異常。

預簽名URL的最大有效期間(可選閱讀)

預簽名 URL 的最大有效期間取決於簽名版本(V4 或 V1)及產生工具。推薦使用V4簽名,最大有效期間為7天,具備更高的安全性。V1簽名雖然支援更長有效期間,但安全性較低,已不再維護,因此不推薦使用。

  • V4 簽名(推薦):採用相對時間來表示有效期間,即“產生簽名時UTC時間 + 有效期間”表示為預簽名URL的到期時間,其中最大有效期間為604800 秒(7 天)。

  • V1 簽名:採用時間戳記 (unix timestamp) 表示有效期間,最大為時間戳記能表示的最大時間。V1簽名和V4簽名的更多差異見V1簽名和V4簽名對比

說明

若通過 STS Token 產生預簽名 URL,其有效期間受限於STS Token 本身的有效期間,最多為 43200 秒(12 小時)。

以下為使用不同工具產生預簽名URL的最大有效期間。

工具

最大有效期間

說明

OSS SDK 2.0

V1:長期(時間戳記上限)

V4:604800秒(7天)

預設使用 V4,可指定 V1。

使用v4簽名時,超出最大有效期間,會報錯。

OSS SDK 1.0

V1:長期(時間戳記上限)

V4:604800秒(7天)

預設使用 V1,可指定 V4。

使用v4簽名時,超出最大有效期間,不會報錯。

ossutil 2.0

V1:長期(時間戳記上限)

V4:604800秒(7天)

預設使用 V4,可指定 V1。

使用v4簽名時,超出最大有效期間,會報錯。

ossutil 1.0

V1:長期(時間戳記上限)

V4:604800秒(7天)

預設使用 V1,可指定 V4。

使用v4簽名時,超出最大有效期間,不會報錯。

控制台

32400秒(9 小時)

-

ossbrowser 2.0

32400秒(9 小時)

僅支援V4。

ossbrowser 1.0

32400秒(9 小時)

僅支援V1。

使用OSS控制台

您可以登入OSS管理主控台,進入目標Bucket的檔案清單,單擊目標檔案後在右側詳情面板到期時間,設定連結有效期間。

使用阿里雲SDK

說明

您需擁有oss:GetObject許可權,第三方才能通過該預簽名URL成功下載檔案。具體授權操作,請參見為RAM使用者授權自訂的權限原則。產生後,您可將連結發送給需要訪問該檔案的第三方。

通過修改代碼中的expiration來設定預簽名URL的到期時間。

Java

更多SDK資訊,請參見Java使用預簽名URL下載檔案

import com.aliyun.oss.*;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.common.comm.SignVersion;

import java.net.URL;
import java.util.Date;

public class Demo {
    public static void main(String[] args) throws Throwable {
        // 以華東1(杭州)的外網Endpoint為例,其它Region請按實際情況填寫。
        String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
        // 從環境變數中擷取訪問憑證。運行本程式碼範例之前,請確保已設定環境變數OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
        // 填寫Bucket名稱,例如examplebucket。
        String bucketName = "examplebucket";
        // 填寫Object完整路徑,例如exampleobject.txt。Object完整路徑中不能包含Bucket名稱。
        String objectName = "exampleobject.txt";
        // 填寫Bucket所在地區。以華東1(杭州)為例,Region填寫為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();

        try {
            // 設定預簽名URL到期時間,單位為毫秒。本樣本以設定到期時間為1小時為例。
            Date expiration = new Date(new Date().getTime() + 3600 * 1000L);
            // 產生以GET方法訪問的預簽名URL。本樣本沒有額外要求標頭,其他人可以直接通過瀏覽器訪問相關內容。
            URL url = ossClient.generatePresignedUrl(bucketName, objectName, expiration);
            System.out.println(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());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }
}

Python

更多SDK資訊,請參見Python使用預簽名URL下載檔案

import argparse
import alibabacloud_oss_v2 as oss

# 建立一個命令列參數解析器,並描述指令碼用途:產生GET方法的預簽名URL請求樣本
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,表示其他服務可用來訪問OSS的網域名稱,非必需參數
parser.add_argument('--endpoint', help='The domain names that other services can use to access OSS')
# 添加命令列參數 --key,表示對象(檔案)在OSS中的鍵名,必需參數
parser.add_argument('--key', help='The name of the object.', required=True)

def main():
    # 解析命令列提供的參數,擷取使用者輸入的值
    args = parser.parse_args()

    # 從環境變數中載入訪問OSS所需的認證資訊,用於身分識別驗證
    credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider()

    # 使用SDK的預設配置建立設定物件,並設定認證提供者
    cfg = oss.config.load_default()
    cfg.credentials_provider = credentials_provider
    
    # 設定設定物件的地區屬性,根據使用者提供的命令列參數
    cfg.region = args.region

    # 如果提供了自訂endpoint,則更新設定物件中的endpoint屬性
    if args.endpoint is not None:
        cfg.endpoint = args.endpoint

    # 使用上述配置初始化OSS用戶端,準備與OSS互動
    client = oss.Client(cfg)

    # 產生預簽名的GET請求
    pre_result = client.presign(
        oss.GetObjectRequest(
            bucket=args.bucket,  # 指定儲存空間名稱
            key=args.key,        # 指定對象鍵名
        )
    )

    # 列印預簽章要求的方法、到期時間和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()  # 指令碼進入點,控製程序流程從這裡開始

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(&region, "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()

	// 檢查bucket名稱是否為空白
	if len(bucketName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, bucket name required")
	}

	// 檢查region是否為空白
	if len(region) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, region required")
	}

	// 檢查object名稱是否為空白
	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)

	// 產生GetObject的預簽名URL
	result, err := client.Presign(context.TODO(), &oss.GetObjectRequest{
		Bucket: oss.Ptr(bucketName),
		Key:    oss.Ptr(objectName),
	},
		oss.PresignExpires(10*time.Minute),
	)
	if err != nil {
		log.Fatalf("failed to get 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 {
		//當返回結果包含簽名頭時,使用預簽名URL發送GET請求時也包含相應的要求標頭,以免出現不一致,導致請求失敗和預簽名錯誤
		log.Printf("signed headers:\n")
		for k, v := range result.SignedHeaders {
			log.Printf("%v: %v\n", k, v)
		}
	}
}

Node.js

更多SDK資訊,請參見Node.js使用預簽名URL下載檔案

const OSS = require("ali-oss");

// 定義一個產生預簽名 URL 的函數
async function generateSignatureUrl(fileName) {
  // 擷取預簽名URL
  const client = await new OSS({
      // 從環境變數中擷取訪問憑證。運行本程式碼範例之前,請確保已設定環境變數OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
      accessKeyId: process.env.OSS_ACCESS_KEY_ID,
      accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET,
      bucket: 'examplebucket',
      // yourregion填寫Bucket所在地區。以華東1(杭州)為例,Region填寫為oss-cn-hangzhou。
      region: 'oss-cn-hangzhou',
      // 設定secure為true,使用HTTPS,避免產生的下載連結被瀏覽器攔截
      secure: true,
      authorizationV4: true
  });

  return await client.signatureUrlV4('GET', 3600, {
      headers: {} // 請根據實際發送的要求標頭設定此處的要求標頭
  }, fileName);
}
// 調用函數並傳入檔案名稱
generateSignatureUrl('yourFileName').then(url => {
  console.log('Generated Signature URL:', url);
}).catch(err => {
  console.error('Error generating signature URL:', err);
});

PHP

更多SDK資訊,請參見PHP使用預簽名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);

// 建立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,用於直接下載對象
);

.NET

更多SDK資訊,請參見.NET使用預簽名URL下載檔案

using Aliyun.OSS;
using Aliyun.OSS.Common;
// 填寫Bucket所在地區對應的Endpoint。以華東1(杭州)為例,Endpoint填寫為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");
// 填寫Bucket名稱,例如examplebucket。
var bucketName = "examplebucket";
// 填寫Object完整路徑,完整路徑中不包含Bucket名稱,例如exampledir/exampleobject.txt。
var objectName = "exampledir/exampleobject.txt";
// 填寫Bucket所在地區對應的Region。以華東1(杭州)為例,Region填寫為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
{
    var metadata = client.GetObjectMetadata(bucketName, objectName);
    var etag = metadata.ETag;
    // 產生預簽名URL。
    var req = new GeneratePresignedUriRequest(bucketName, objectName, SignHttpMethod.Get)
      {
        // 設定預簽名URL到期時間,預設值為3600秒。
        Expiration = DateTime.UtcNow.AddHours(1),
    };
    var uri = client.GeneratePresignedUri(req);
    // 列印產生的預簽名URL
    Console.WriteLine("Generated Signed URL: " + uri);
}
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);
}

Android

更多SDK資訊,請參見Android使用預簽名URL下載檔案

// 填寫Bucket名稱,例如examplebucket。
String bucketName = "examplebucket";
// 填寫不包含Bucket名稱在內源Object的完整路徑,例如exampleobject.txt。
String objectKey = "exampleobject.txt";
String url = null;
try {
    // 產生用於下載檔案的預簽名URL。
    GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucketName, objectKey);
    // 設定預簽名URL的到期時間為30分鐘。
    request.setExpiration(30*60);
    request.setMethod(HttpMethod.GET);
    url = oss.presignConstrainedObjectURL(request);
    Log.d("url", url);
} catch (ClientException e) {
    e.printStackTrace();
}

iOS

更多SDK資訊,請參見iOS使用預簽名URL下載檔案

// 填寫Bucket名稱。
NSString *bucketName = @"examplebucket";
// 填寫Object名稱。
NSString *objectKey = @"exampleobject.txt";
__block NSString *urlString;
// 產生用於下載的預簽名URL,並指定預簽名URL到期時間為30分鐘。
OSSTask *task = [client presignConstrainURLWithBucketName:bucketName
                                            withObjectKey:objectKey
                                               httpMethod:@"GET"
                                   withExpirationInterval:30 * 60
                                           withParameters:@{}];
[task continueWithBlock:^id _Nullable(OSSTask * _Nonnull task) {
    if (task.error) {
        NSLog(@"presign error: %@", task.error);
    } else {
        urlString = task.result;
        NSLog(@"url: %@", urlString);
    }
    return nil;
}];

C++

更多SDK資訊,請參見C++使用預簽名URL下載檔案

#include <alibabacloud/oss/OssClient.h>
using namespace AlibabaCloud::OSS;

int main(void)
{
    /* 初始化OSS帳號資訊。*/
            
    /* yourEndpoint填寫Bucket所在地區對應的Endpoint。以華東1(杭州)為例,Endpoint填寫為https://oss-cn-hangzhou.aliyuncs.com。*/
    std::string Endpoint = "yourEndpoint";
    /* yourRegion填寫Bucket所在地區對應的Region。以華東1(杭州)為例,Region填寫為cn-hangzhou。*/
    std::string Region = "yourRegion";
    /* 填寫Bucket名稱,例如examplebucket。*/
    std::string BucketName = "examplebucket";
    /* 填寫Object完整路徑,完整路徑中不能包含Bucket名稱,例如exampledir/exampleobject.txt。*/ 
    std::string GetobjectUrlName = "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);

    /* 設定簽名有效時間長度,最大有效時間為32400秒。*/
    std::time_t t = std::time(nullptr) + 1200;
    /* 產生預簽名URL。*/
    auto genOutcome = client.GeneratePresignedUrl(BucketName, GetobjectUrlName, t, Http::Get);
    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;
}

Ruby

更多SDK資訊,請參見Ruby使用預簽名URL下載檔案

require 'aliyun/oss'

client = Aliyun::OSS::Client.new(
  # Endpoint以華東1(杭州)為例,其它Region請按實際情況填寫。
  endpoint: 'https://oss-cn-hangzhou.aliyuncs.com',
  # 從環境變數中擷取訪問憑證。運行本程式碼範例之前,請確保已設定環境變數OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
  access_key_id: ENV['OSS_ACCESS_KEY_ID'],
  access_key_secret: ENV['OSS_ACCESS_KEY_SECRET']
)
# 填寫Bucket名稱,例如examplebucket。
bucket = client.get_bucket('examplebucket')

# 產生預簽名URL,並指定URL有效時間為1小時(3600秒)。
puts bucket.object_url('my-object', true, 3600)

C

更多SDK資訊,請參見C使用預簽名URL下載檔案

#include "oss_api.h"
#include "aos_http_io.h"
/* yourEndpoint填寫Bucket所在地區對應的Endpoint。以華東1(杭州)為例,Endpoint填寫為https://oss-cn-hangzhou.aliyuncs.com。*/
const char *endpoint = "yourEndpoint";
/* 填寫Bucket名稱,例如examplebucket。*/
const char *bucket_name = "examplebucket";
/* 填寫Object完整路徑,完整路徑中不能包含Bucket名稱,例如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);
    /* 用char*類型的字串初始化aos_string_t類型。*/
    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表示不使用。*/
    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;
    /* 重新建立一個記憶體池,第二個參數是NULL,表示沒有繼承其它記憶體池。*/
    aos_pool_create(&pool, NULL);
    /* 建立並初始化options,該參數包括endpoint、access_key_id、acces_key_secret、is_cname、curl等全域配置資訊。*/
    oss_request_options_t *oss_client_options;
    /* 在記憶體池中分配記憶體給options。*/
    oss_client_options = oss_request_options_create(pool);
    /* 初始化Client的選項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_GET;
    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("臨時下載URL: %s\n", url_str);     
    /* 釋放記憶體池,相當於釋放了請求過程中各資源分派的記憶體。*/
    aos_pool_destroy(pool);
    /* 釋放之前分配的全域資源。*/
    aos_http_io_deinitialize();
    return 0;
}

使用命令列工具ossutil

對儲存空間examplebucket裡的example.txt對象,產生有效期間為1小時的預簽名URL。

ossutil presign oss://examplebucket/example.txt --expires-duration 1h

關於使用ossutil產生預簽名URL的更多樣本, 請參見presign(產生預簽名URL)

使用圖形化管理工具ossbrowser

ossbrowser支援Object層級的操作與控制台支援的操作類似,請按照ossbrowser介面指引完成擷取預簽名URL的操作。關於如何使用ossbrowser,請參見常用操作

擷取長期有效連結

您可以通過以下兩種方式擷取不含簽名、無到期時間限制的檔案URL(連結)。

  • 方式一:設定檔案為公用讀取(不推薦)

    將檔案ACL設定為"公用讀取",擷取永久有效檔案URL。配置簡單、無需額外工具,但檔案地址完全公開,任何人都可訪問,易被惡意爬蟲或刷流量。建議配合OSS 防盜鏈(Referer白名單)使用,但仍存在來源站點暴露風險。

  • 方式二:通過CDN提供公用讀取訪問(推薦)

    檔案保持私人,通過CDN實現公用訪問。開啟CDN的OSS私人Bucket回源功能後,您可以通過CDN加速網域名稱訪問私人Bucket內的所有資源,原URL的私人鑒權方式將失效。相比方式一,OSS不直接暴露,安全性更高,支援加速與存取控制功能。建議啟用CDN的Referer防盜鏈URL鑒權,防止連結被濫用。

如何拼接長期有效檔案URL

您可根據網域名稱類型拼接檔案訪問地址。

網域名稱類型

URL格式

樣本

OSS預設網域名稱

https://<BucketName>.<Endpoint>/<ObjectName>

例如,華東1(杭州)地區下名為examplebucket的Bucket下有名為example的檔案夾,檔案夾內有個名為example.jpg的檔案。

  • 外網訪問URL:https://examplebucket.oss-cn-hangzhou.aliyuncs.com/example/example.jpg

  • 內網訪問URL(供同地區ECS執行個體訪問):https://examplebucket.oss-cn-hangzhou-internal.aliyuncs.com/example/example.jpg

自訂網域名

https://<YourDomainName>/<ObjectName>

例如,您在華東1(杭州)地區下的examplebucket綁定了自訂網域名example.com,且該Bucket下包含example.jpg的檔案,則該檔案URL為https://example.com/example.jpg

CDN加速網域名稱

https://<CDN 加速網域名稱>/<ObjectName>

例如,當CDN加速網域名稱為aliyundoc.com,需要訪問根目錄下的檔案image_01.jpg時,檔案URL為http://aliyundoc.com/image_01.jpg

配置HTTPS協議

連結協議由訪問網域名稱(Endpoint)決定。預設訪問網域名稱無需配置,直接支援HTTPS;使用自訂網域名時,需先完成認證託管,才能啟用 HTTPS 協議。

  • OSS控制台:產生連結時,可在詳情面板選擇協議,預設即為 HTTPS。

  • ossutil/SDK:取決於您設定的 Endpoint。以 https:// 開頭,則使用 HTTPS。

預覽時中文亂碼

設定檔案中繼資料的Content-Type欄位為text/plain;charset=utf-8,明確指定瀏覽器以 UTF-8編碼方式渲染檔案內容,確保內容正確顯示。

  1. 登入OSS管理主控台

  2. 單擊Bucket 列表,然後單擊目標Bucket名稱。

  3. 在左側導覽列,選擇檔案管理 > 檔案清單

  4. 在目標Object右側選擇設定檔案中繼資料

  5. HTTP標準屬性地區,將Content-Type設定為text/plain;charset=utf-8

  6. 單擊確定

限制訪問來源

通過配置Referer防盜鏈,只允許指定網站訪問 OSS 資源,拒絕其他來源的請求。

例如,只允許來自您的官網https://example.com的訪問請求,其他來源將被拒絕。

授權第三方更多操作

除了預簽名URL,阿里雲還提供了更靈活的臨時授權方式——STS臨時訪問憑證。如果您希望第三方對OSS的操作不只是下載,還能執行如列舉、拷貝等操作,建議您瞭解並使用STS臨時訪問憑證,詳情請參見使用STS臨時訪問憑證訪問OSS

處理圖片

您可以產生帶圖片處理參數的預簽名URL來處理圖片,例如調整大小,添加浮水印等。