全部產品
Search
文件中心

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

更新時間:Mar 08, 2025

預設情況下,OSS儲存空間中檔案的讀寫權限是私人,僅檔案擁有者可以訪問。但檔案擁有者可以對指定檔案產生具有臨時存取權限的預簽名URL,以允許他人使用該預簽名URL在有效期間內下載檔案。

注意事項

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

  • 產生GET方法的預簽名URL時,您必須具有oss:GetObject許可權。具體操作,請參見RAM Policy常見樣本

    說明

    產生預簽名URL過程中,SDK利用本機存放區的密鑰資訊,根據特定演算法計算出簽名(signature),然後將其附加到URL上,以確保URL的有效性和安全性。這一系列計算和構造URL的操作都是在用戶端完成,不涉及網路請求到服務端。因此,產生預簽名URL時不需要授予調用者特定許可權。但是,為避免第三方使用者無法對預簽名URL授權的資源執行相關操作,需要確保調用產生預簽名URL介面的身份主體被授予對應的許可權。

  • 預簽名URL在有效期間內可多次訪問,超期後,需執行步驟一重建預簽名URL以繼續訪問檔案。

流程概覽

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

詳細步驟

步驟一:檔案擁有者產生GET方法的簽名URL

說明
  • 通過OSS控制台和ossbrowser產生的預簽名URL,最大有效時間長度為32400秒(9 小時)。

  • 通過命令列工具ossutil和SDK產生的預簽名URL,最大有效時間長度為7天。

  • 若使用STSToken來產生預簽名URL,則最大有效時間長度為43200秒(12小時)。

使用OSS控制台

您可以通過OSS控制台組建檔案的預簽名URL。

  1. 登入OSS管理主控台

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

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

  4. 擷取預簽名URL。

    1. 單擊目標檔案名稱。

    2. 詳情面板配置以下參數,然後單擊復制文件 URL

      image

      參數

      說明

      到期時間

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

      取值範圍:60~32400

      單位:秒

      如果您希望設定更長到期時間的檔案URL,您可以使用sdk、ossutil等工具。

      自有域名

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

      僅當Bucket綁定自訂網域名後可配置此項。更多資訊,請參見綁定自訂網域名

      使用HTTPS

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

使用圖形化管理工具ossbrowser

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

使用阿里雲SDK

以下僅列舉常見語言的產生預簽名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執行個體。
        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下載檔案

# -*- coding: utf-8 -*-
import oss2
from oss2.credentials import EnvironmentVariableCredentialsProvider

# 從環境變數中擷取訪問憑證。運行本程式碼範例之前,請確保已設定環境變數OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
auth = oss2.ProviderAuthV4(EnvironmentVariableCredentialsProvider())

# 填寫Bucket所在地區對應的Endpoint。以華東1(杭州)為例,Endpoint填寫為https://oss-cn-hangzhou.aliyuncs.com。
endpoint = "https://oss-cn-hangzhou.aliyuncs.com"

# 填寫Endpoint對應的Region資訊,例如cn-hangzhou。注意,v4簽名下,必須填寫該參數
region = "cn-hangzhou"

# yourBucketName填寫儲存空間名稱。
bucket = oss2.Bucket(auth, endpoint, "yourBucketName", region=region)

# 填寫Object完整路徑,例如exampledir/exampleobject.txt。Object完整路徑中不能包含Bucket名稱。
object_name = 'exampledir/exampleobject.txt'

# 產生下載檔案的預簽名URL,有效時間為600秒。
# 產生預簽名URL時,OSS預設會對Object完整路徑中的正斜線(/)進行轉義,從而導致產生的簽名URL無法直接使用。
# 設定slash_safe為True,OSS不會對Object完整路徑中的正斜線(/)進行轉義,此時產生的簽名URL可以直接使用。
url = bucket.sign_url('GET', object_name, 600, slash_safe=True)
print('預簽名URL的地址為:', url)

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
if (is_file(__DIR__ . '/../autoload.php')) {
    require_once __DIR__ . '/../autoload.php';
}
if (is_file(__DIR__ . '/../vendor/autoload.php')) {
    require_once __DIR__ . '/../vendor/autoload.php';
}

use OSS\OssClient;
use OSS\Core\OssException;
use OSS\Http\RequestCore;
use OSS\Http\ResponseCore;
use OSS\Credentials\EnvironmentVariableCredentialsProvider;

// 從環境變數中擷取訪問憑證。運行本程式碼範例之前,請確保已設定環境變數OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
$provider = new EnvironmentVariableCredentialsProvider();
// yourEndpoint填寫Bucket所在地區對應的Endpoint。以華東1(杭州)為例,Endpoint填寫為https://oss-cn-hangzhou.aliyuncs.com。
$endpoint = "yourEndpoint";
// 填寫Bucket名稱。
$bucket= "examplebucket";
// 填寫不包含Bucket名稱在內的Object完整路徑。
$object = "exampleobject.txt";
// 指定預簽名URL的到期時間為600s(最長可達32400s)。
$timeout = 600;
try {
    $config = array(  
        "provider" => $provider,
        "endpoint" => $endpoint,
        'signatureVersion'=>OssClient::OSS_SIGNATURE_VERSION_V4,
        "region"=> "cn-hangzhou"
    );
    $ossClient = new OssClient($config);
    // 產生預簽名URL。
    $signedUrl = $ossClient->signUrl($bucket, $object, $timeout, "GET");
    print_r($signedUrl);
} catch (OssException $e) {
    printf(__FUNCTION__ . ": FAILED\n");
    printf($e->getMessage() . "\n");
    return;
}           

.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";
var objectContent = "More than just cloud.";
// 填寫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);
conf.SetRegion(region);
try
{
    // 產生預簽名URL。
    var generatePresignedUriRequest = new GeneratePresignedUriRequest(bucketName, objectName, SignHttpMethod.Put)
    {
        // 設定預簽名URL到期時間,預設值為3600秒。
        Expiration = DateTime.Now.AddHours(1),
    };
    var signedUrl = client.GeneratePresignedUri(generatePresignedUriRequest);
}
catch (OssException ex)
{
    Console.WriteLine("Failed with error code: {0}; Error info: {1}. \nRequestID:{2}\tHostID:{3}",
        ex.ErrorCode, ex.Message, ex.RequestId, ex.HostId);
}
catch (Exception ex)
{
    Console.WriteLine("Failed with error info: {0}", ex.Message);
}

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***********1Uuu%2F20241115%2Fcn-hangzhou%2Foss%2Faliyun_v4_request&x-oss-signature=6e7*************************1eb79d96

使用命令列工具ossutil

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

ossutil presign oss://examplebucket/example.txt

關於使用ossutil產生預簽名URL的具體操作, 請參見presign(產生預簽名URL)

步驟二:其他人使用GET方法的簽名URL下載檔案

使用瀏覽器下載

複製步驟一產生的URL並粘貼到瀏覽器地址欄,按斷行符號鍵即可下載檔案。

使用curl命令下載

在終端輸入以下命令,將 <presigned_url> 替換為步驟一產生的預簽名 URL。

curl -SO "<presigned_url>"

命令樣本:

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=LTAI5************/20241112/cn-hangzhou/oss/aliyun_v4_request&x-oss-signature=ed5a939feb8d79a389572719f7e2939939936d0**********"

使用wget命令下載

在終端輸入以下命令,將<presigned_url>替換為步驟一產生的預簽名 URL,檔案將以自訂檔案名稱 example.txt儲存在目前的目錄中。

wget -O example.txt "<presigned_url>"

命令樣本:

wget -O example.txt "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=LTAI5************/20241112/cn-hangzhou/oss/aliyun_v4_request&x-oss-signature=ed5a939feb8d79a389572719f7e2939939936d0**********"

使用代碼下載

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=LTAI5************/20241112/cn-hangzhou/oss/aliyun_v4_request&x-oss-signature=ed5a939feb8d79a389572719f7e2939939936d0**********";
        // 填寫檔案儲存的目標路徑,包括檔案名稱和副檔名。
        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();
    }
}

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=LTAI5************/20241112/cn-hangzhou/oss/aliyun_v4_request&x-oss-signature=ed5a939feb8d79a389572719f7e2939939936d0**********"
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=LTAI5************/20241112/cn-hangzhou/oss/aliyun_v4_request&x-oss-signature=ed5a939feb8d79a389572719f7e2939939936d0**********"
    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)
    }
}

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=LTAI5************/20241112/cn-hangzhou/oss/aliyun_v4_request&x-oss-signature=ed5a939feb8d79a389572719f7e2939939936d0**********";
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);
});

browser.js

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=LTAI5************/20241112/cn-hangzhou/oss/aliyun_v4_request&x-oss-signature=ed5a939feb8d79a389572719f7e2939939936d0**********";
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

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();
        }
    }
}

iOS

#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=LTAI5************/20241112/cn-hangzhou/oss/aliyun_v4_request&x-oss-signature=ed5a939feb8d79a389572719f7e2939939936d0**********";
        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,並指定檔案版本,從而允許第三方下載歷史版本的檔案。

Java

import com.aliyun.oss.*;
import com.aliyun.oss.common.auth.*;
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執行個體。
        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

# -*- coding: utf-8 -*-
import oss2
from oss2.credentials import EnvironmentVariableCredentialsProvider
import requests

# 從環境變數中擷取訪問憑證。運行本程式碼範例之前,請確保已設定環境變數OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
auth = oss2.ProviderAuthV4(EnvironmentVariableCredentialsProvider())

# 填寫Bucket所在地區對應的Endpoint。以華東1(杭州)為例,Endpoint填寫為https://oss-cn-hangzhou.aliyuncs.com。
endpoint = "https://oss-cn-hangzhou.aliyuncs.com"

# 填寫Endpoint對應的Region資訊,例如cn-hangzhou。注意,v4簽名下,必須填寫該參數
region = "cn-hangzhou"

# yourBucketName填寫儲存空間名稱。
bucket = oss2.Bucket(auth, endpoint, "yourBucketName", region=region)

# 填寫Object完整路徑,例如exampledir/exampleobject.txt。Object完整路徑中不能包含Bucket名稱。
object_name = 'exampledir/exampleobject.txt'

# 指定Header。
headers = dict()
# 填寫Object的versionId。
headers["versionId"] = "CAEQARiBgID8rumR2hYiIGUyOTAyZGY2MzU5MjQ5ZjlhYzQzZjNlYTAyZDE3****"

# 產生上傳檔案的預簽名URL,有效時間為600秒。
# 產生預簽名URL時,OSS預設會對Object完整路徑中的正斜線(/)進行轉義,從而導致產生的預簽名URL無法直接使用。
# 設定slash_safe為True,OSS不會對Object完整路徑中的正斜線(/)進行轉義,此時產生的預簽名URL可以直接使用。
url = bucket.sign_url('PUT', object_name, 600, slash_safe=True, headers=headers)
print('預簽名URL的地址為:', url)

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
if (is_file(__DIR__ . '/../autoload.php')) {
    require_once __DIR__ . '/../autoload.php';
}
if (is_file(__DIR__ . '/../vendor/autoload.php')) {
    require_once __DIR__ . '/../vendor/autoload.php';
}

use OSS\OssClient;
use OSS\Core\OssException;
use OSS\Http\RequestCore;
use OSS\Http\ResponseCore;
use OSS\Credentials\EnvironmentVariableCredentialsProvider;

// 從環境變數中擷取訪問憑證。運行本程式碼範例之前,請確保已設定環境變數OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
$provider = new EnvironmentVariableCredentialsProvider();
// yourEndpoint填寫Bucket所在地區對應的Endpoint。以華東1(杭州)為例,Endpoint填寫為https://oss-cn-hangzhou.aliyuncs.com。
$endpoint = "yourEndpoint";
// 填寫Bucket名稱。
$bucket= "examplebucket";
// 填寫不包含Bucket名稱在內的Object完整路徑。
$object = "exampleobject.txt";
// 指定預簽名URL的到期時間為600s(最長可達32400s)。
$timeout = 600;
try{
  $config = array(
      "provider" => $provider,
      "endpoint" => $endpoint,
      "signatureVersion" => OssClient::OSS_SIGNATURE_VERSION_V4,
      "region"=> "cn-hangzhou"
  );
  $ossClient = new OssClient($config);
  $options = array(
      // 填寫Object的versionId。
      $ossClient::OSS_VERSION_ID=>"CAEQEhiBgIDmgPf8mxgiIDA1YjZlNDIxY2ZmMzQ1MmU5MTM1Y2M4Yzk4NjIx****"
  );
  // 產生預簽名URL。
  $signedUrl = $ossClient->signUrl($bucket, $object, $timeout, "GET", $options);
  print_r($signedUrl);
} catch(OssException $e) {
  printf($e->getMessage() . "\n");
}

產生可以控制下載行為的簽名URL

通過攜帶要求標頭參數,您可以預設下載行為(如強制瀏覽器下載或按指定編碼解析內容)。在產生GET方法的預簽名URL時,如果指定了要求標頭,也要確保在使用預簽名URL時包含相應的要求標頭,以免出現不一致,導致請求失敗和預簽名錯誤。可設定的Header參數,請參見GetObject。您還可以自訂中繼資料以便檔案管理,詳細內容請參見管理檔案中繼資料

例如,若您希望通過預簽名URL訪問.txt檔案並正確顯示中文內容,避免亂碼,需在產生時指定Content-Type: text/plain;charset=utf-8,並確保使用該預簽名URL時也攜帶相同要求標頭。

  1. 產生GET方法的預簽名URL

Java

import com.aliyun.oss.*;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.common.comm.SignVersion;
import com.aliyun.oss.internal.OSSHeaders;
import com.aliyun.oss.model.GeneratePresignedUrlRequest;

import 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";
        // 建立OSSClient執行個體。
        String region = "cn-hangzhou";
        ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
        clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);
        OSS ossClient = OSSClientBuilder.create()
                .endpoint(endpoint)
                .credentialsProvider(credentialsProvider)
                .clientConfiguration(clientBuilderConfiguration)
                .region(region)
                .build();

        // 佈建要求頭。
        Map<String, String> headers = new HashMap<>();
        // 指定ContentType。
        headers.put(OSSHeaders.CONTENT_TYPE, "text/txt");
        URL signedUrl = null;
        try {
            // 指定產生的預簽名URL到期時間,單位為毫秒。本樣本以設定到期時間為1小時為例。
            Date expiration = new Date(new Date().getTime() + 3600 * 1000L);
            // 產生預簽名URL。
            GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucketName, objectName, HttpMethod.GET);
            // 設定到期時間。
            request.setExpiration(expiration);
            // 將要求標頭加入到request中。
            request.setHeaders(headers);
            // 通過HTTP GET請求產生預簽名URL。
            signedUrl = ossClient.generatePresignedUrl(request);
            // 列印預簽名URL。
            System.out.println("signed url for putObject: " + signedUrl);
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        }
    }
}

Python

# -*- coding: utf-8 -*-
import oss2
from oss2.credentials import EnvironmentVariableCredentialsProvider

# 從環境變數中擷取訪問憑證。運行本程式碼範例之前,請確保已設定環境變數OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
auth = oss2.ProviderAuthV4(EnvironmentVariableCredentialsProvider())

# 填寫Bucket所在地區對應的Endpoint。以華東1(杭州)為例,Endpoint填寫為https://oss-cn-hangzhou.aliyuncs.com。
endpoint = "https://oss-cn-hangzhou.aliyuncs.com"

# 填寫Endpoint對應的Region資訊,例如cn-hangzhou。注意,v4簽名下,必須填寫該參數
region = "cn-hangzhou"

# yourBucketName填寫儲存空間名稱。
bucket = oss2.Bucket(auth, endpoint, "yourBucketName", region=region)

# 填寫Object完整路徑,例如exampledir/exampleobject.txt。Object完整路徑中不能包含Bucket名稱。
object_name = 'exampledir/exampleobject.txt'

# 指定Header。
headers = dict()
# 指定Content-Type。
headers['Content-Type'] = 'text/plain'

# 指定HTTP查詢參數。
params = dict()
# 設定單連結限速,單位為bit,例如限速100 KB/s。
# params['x-oss-traffic-limit'] = str(100 * 1024 * 8)
# 指定IP地址或者IP位址區段。
# params['x-oss-ac-source-ip'] = "127.0.0.1"
# 指定子網路遮罩中1的個數。
# params['x-oss-ac-subnet-mask'] = "32"
# 指定VPC ID。
# params['x-oss-ac-vpc-id'] = "vpc-t4nlw426y44rd3iq4xxxx"
# 指定是否允許轉寄請求。
# params['x-oss-ac-forward-allow'] = "true"

# 產生下載檔案的預簽名URL,有效時間為600秒。
# 產生預簽名URL時,OSS預設會對Object完整路徑中的正斜線(/)進行轉義,從而導致產生的預簽名URL無法直接使用。
# 設定slash_safe為True,OSS不會對Object完整路徑中的正斜線(/)進行轉義,此時產生的預簽名URL可以直接使用。
url = bucket.sign_url('GET', object_name, 600, slash_safe=True, headers=headers, params=params)
print('預簽名URL的地址為:', url)

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),
		RequestCommon: oss.RequestCommon{
			Headers: map[string]string{
				"Content-Type": "text/txt; charset=utf-8", // 佈建要求頭資訊,指定Content-Type為text/txt; charset=utf-8
			},
		},
	},
	)
	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)
		}
	}
}
  1. 其他人使用GET方法的預簽名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=LTAI************ACXg********************&x-oss-signature=f1746f121783eed5dab2d665da95fbca08505263e27476a46f88dbe3702af8a9***************************************" \
-H "Content-Type: text/txt" \
-o "C:/downloads/myfile.txt"
import com.aliyun.oss.internal.OSSHeaders;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import java.io.*;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

public class Demo {
    public static void main(String[] args) throws Throwable {
        // 替換為實際預簽名URL
        URL signedUrl = new URL("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=LTAI********************%2F20241113%2Fcn-hangzhou%2Foss%2Faliyun_v4_request&x-oss-signature=f174****************************************************702af8a9"); 
        // 填寫下載到本地檔案的完整路徑。
        String pathName = "C:/downloads/myfile.txt";

        // 頭部可以通過上下文傳遞或保持相同
        // 佈建要求頭。
        Map<String, String> headers = new HashMap<>();
        // 指定ContentType。
        headers.put(OSSHeaders.CONTENT_TYPE, "text/txt");

        // 通過預簽名URL下載檔案,以HttpClients為例說明。
        getObjectWithHttp(signedUrl, pathName, headers);
    }

    public static void getObjectWithHttp(URL signedUrl, String pathName, Map<String, String> headers) throws IOException {
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse response = null;
        try {
            HttpGet get = new HttpGet(signedUrl.toString());
            // 如果產生預簽名URL時設定了header參數,則調用預簽名URL下載檔案時也需要將這些參數發送至服務端。
            for (Map.Entry header : headers.entrySet()) {
                get.addHeader(header.getKey().toString(), header.getValue().toString());
            }
            httpClient = HttpClients.createDefault();
            response = httpClient.execute(get);
            System.out.println("返回下載狀態代碼:" + response.getStatusLine().getStatusCode());
            if (response.getStatusLine().getStatusCode() == 200) {
                System.out.println("使用網路程式庫下載成功");
            }
            System.out.println(response.toString());
            // 儲存檔案到磁碟。
            saveFileToLocally(response.getEntity().getContent(), pathName);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            response.close();
            httpClient.close();
        }
    }

    public static void saveFileToLocally(InputStream inputStream, String pathName) throws IOException {
        DataInputStream in = null;
        OutputStream out = null;
        try {
            in = new DataInputStream(inputStream);
            out = new DataOutputStream(new FileOutputStream(pathName));
            int bytes = 0;
            byte[] bufferOut = new byte[1024];
            while ((bytes = in.read(bufferOut)) != -1) {
                out.write(bufferOut, 0, bytes);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            in.close();
            out.close();
        }
    }
}
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=LTAI5************/20241112/cn-hangzhou/oss/aliyun_v4_request&x-oss-signature=ed5a939feb8d79a389572719f7e2939939936d0**********"
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)
package main

import (
	"io"
	"log"
	"net/http"
	"os"
)

func main() {
	// 填寫產生的預簽名的URL
	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=LTAI5************/20241112/cn-hangzhou/oss/aliyun_v4_request&x-oss-signature=ed5a939feb8d79a389572719f7e2939939936d0**********"

	// 通過上述產生的預簽名URL,使用HTTP GET方法下載檔案
	req, err := http.NewRequest(http.MethodGet, url, nil)
	if err != nil {
		log.Fatalf("Failed to create PUT request: %v", err)
	}

	//佈建要求頭Content-Type
	req.Header.Set("Content-Type", "text/txt; charset=utf-8")

	// 發起請求
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		log.Fatalf("Failed to upload file: %v", err)
	}
	defer resp.Body.Close()

	// 定義要寫入的本地檔案路徑
	filePath := "C:/downloads/myfile.txt"

	// 建立或開啟本地檔案
	file, err := os.Create(filePath)
	if err != nil {
		log.Fatalf("failed to create or open file: %v", err)
	}
	defer file.Close() // 確保在函數結束時關閉檔案

	// 使用io.Copy將檔案內容寫入到本地檔案中
	n, err := io.Copy(file, resp.Body)
	if err != nil {
		log.Fatalf("failed to read object %v", err)
	}

	// 關閉響應體
	err = resp.Body.Close()
	if err != nil {
		log.Printf("failed to close response body: %v", err)
	}

	log.Printf("wrote %d bytes to file: %s\n", n, filePath)
}

使用自訂網域名產生可以實現預覽的簽名URL

若您希望通過自訂網域名產生預簽名URL以實現預覽效果,請確保已綁定自訂網域名。如果尚未綁定,請參考綁定自訂網域名至Bucket預設網域名稱進行操作。若已綁定,您可以直接參考下文。

使用OSS控制台

  1. 登入OSS管理主控台

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

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

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

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

    2.png

使用圖形化管理工具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 java.net.URL;
import java.util.Date;

public class Demo {
    public static void main(String[] args) throws Throwable {
        // yourEndpoint請填寫您的自訂網域名。例如http://static.example.com。
        String endpoint = "http://static.example.com";
        // Endpoint請填寫您對應的Region資訊,例如cn-hangzhou。
        String region = "cn-hangzhou";

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

        // 建立OSSClient執行個體。
        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);
            // 產生以GET方法訪問的預簽名URL。本樣本沒有額外要求標頭,其他人可以直接通過瀏覽器訪問相關內容。
            String bucketName = "examplebucket";
            String objectName = "demo.png";
            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
# -*- coding: utf-8 -*-
import oss2
from oss2.credentials import EnvironmentVariableCredentialsProvider

# 從環境變數中擷取訪問憑證。運行本程式碼範例之前,請確保已設定環境變數OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
auth = oss2.ProviderAuthV4(EnvironmentVariableCredentialsProvider())

# 填寫Endpoint對應的Region資訊,例如cn-hangzhou。注意,v4簽名下,必須填寫該參數
region = "cn-hangzhou"

# 填寫自訂網域名,例如static.example.com。
endpoint = 'http://static.example.com'

# yourBucketName填寫儲存空間名稱。
bucket = oss2.Bucket(auth, endpoint, "yourBucketName", region=region, is_cname=True)


# 填寫Object完整路徑,例如exampledir/exampleobject.txt。Object完整路徑中不能包含Bucket名稱。
object_name = 'exampledir/exampleobject.txt'

# 產生下載檔案的預簽名URL,有效時間為600秒。
# 產生預簽名URL時,OSS預設會對Object完整路徑中的正斜線(/)進行轉義,從而導致產生的預簽名URL無法直接使用。
# 設定slash_safe為True,OSS不會對Object完整路徑中的正斜線(/)進行轉義,此時產生的預簽名URL可以直接使用。
url = bucket.sign_url('GET', object_name, 600, slash_safe=True, params=params)
print('預簽名URL的地址為:', 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);
});
PHP
<?php
if (is_file(__DIR__ . '/../autoload.php')) {
    require_once __DIR__ . '/../autoload.php';
}
if (is_file(__DIR__ . '/../vendor/autoload.php')) {
    require_once __DIR__ . '/../vendor/autoload.php';
}

use OSS\OssClient;
use OSS\Core\OssException;
use OSS\Http\RequestCore;
use OSS\Http\ResponseCore;
use OSS\Credentials\EnvironmentVariableCredentialsProvider;

// 從環境變數中擷取訪問憑證。運行本程式碼範例之前,請確保已設定環境變數OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
$provider = new EnvironmentVariableCredentialsProvider();
// yourEndpoint填寫Bucket所在地區對應的Endpoint。以華東1(杭州)為例,Endpoint填寫為http://static.example.com。
$endpoint = "http://static.example.com";
// 填寫Bucket名稱。
$bucket= "examplebucket";
// 填寫不包含Bucket名稱在內的Object完整路徑。
$object = "exampleobject.txt";
// 指定預簽名URL的到期時間為600s(最長可達32400s)。
$timeout = 600;
try {
    $config = array(  
        "provider" => $provider,
        "endpoint" => $endpoint,
        'signatureVersion'=>OssClient::OSS_SIGNATURE_VERSION_V4,
        "cname"	=> true,
        "region"=> "cn-hangzhou"
    );
    $ossClient = new OssClient($config);
    // 產生預簽名URL。
    $signedUrl = $ossClient->signUrl($bucket, $object, $timeout, "GET");
    print_r($signedUrl);
} catch (OssException $e) {
    printf(__FUNCTION__ . ": FAILED\n");
    printf($e->getMessage() . "\n");
    return;
}
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命令自動使用自訂網域名,而無需每次在命令中手動指定自訂網域名,您可以在設定檔中添加自訂網域名,

批量產生預簽名URL

說明
  • OSS控制台僅支援大量匯出目前的目錄下檔案的預簽名URL,不能匯出子目錄下檔案的預簽名URL。若需要匯出目錄及其子目錄下所有檔案的預簽名URL,建議使用命令列工具ossutil。

  • 若需使用SDK批量擷取預簽名URL,具體方法是使用GetBucket (ListObjects)介面擷取所有Object名稱,然後逐個產生預簽名URL。

使用OSS控制台

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

  2. 匯出URL列表面板,配置以下參數:

    參數

    說明

    使用HTTPS

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

    到期時間

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

    取值範圍:60~32400

    單位:秒

    自有域名

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

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

    傳輸加速網域名稱

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

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

  3. 單擊確定,然後將URL列表檔案儲存到本地。

使用命令列工具ossutil

  • 對儲存空間examplebucket裡的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)

瞭解更多

什麼是簽名URL

預簽名URL是一種安全連結,通過加密簽名和有效期間驗證,臨時授權訪問特定的OSS檔案。產生預簽名URL時,本地基於AK/SK金鑰組資源路徑、到期時間等參數進行加密計算,產生簽名參數並將其添加到URL中,形成完整的預簽名URL,其典型格式為:https://BucketName.Endpoint/Object?簽名參數

當第三方訪問該連結時,OSS會校正簽名參數,若參數被篡改或到期則拒絕訪問,以下為預簽名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***********1Uuu%2F20241115%2Fcn-hangzhou%2Foss%2Faliyun_v4_request&x-oss-signature=6e7*************************1eb79d96

通過這種方式,檔案擁有者可以安全地授權第三方訪問檔案,而無需暴露密鑰。

適用情境

  • 短期檔案分享權限設定:第三方申請訪問指定檔案時,後端便產生帶有效期間的預簽名URL並返回給前端,前端將該URL提供給第三方,第三方在連結有效期間內可以安全地上傳或下載檔案。

  • 靈活訪問:檔案擁有者可以通過郵件或聊天工具等方式分享預簽名URL,第三方擷取URL後在瀏覽器地址欄粘貼即可下載檔案。

常見問題

如何擷取長期有效且不帶簽名的URL?

如需擷取不存在預簽名和到期時間的URL,您需要將檔案設定為公用讀取許可權。以下是實現公用讀取的兩種方式:

警告

設定為公用讀取後,互連網上任何使用者都可以訪問該檔案,這有可能造成您資料的外泄以及費用激增,建議您使用包含預簽名和到期時間的URL。

  1. 設定Object ACL:將 OSS 檔案的使用權限設定為公用讀取。在這種情況下,檔案的 URL 將沒有有效期間,任何人都可以訪問。為了防止檔案被其他網站盜用,您需要在 OSS 中配置防盜鏈

    • 如果您使用的是OSS預設網域名稱,檔案URL的格式為https://BucketName.Endpoint/ObjectName。其中,ObjectName需填寫包含檔案夾以及檔案尾碼在內的該檔案的完整路徑。各地區的Endpoint資訊介紹,請參見OSS地區和訪問網域名稱

      例如,華東1(杭州)地區下名為examplebucket的Bucket下有名為example的檔案夾,檔案夾內有個名為example.jpg的檔案。則檔案URL為:
      外網訪問URL:https://examplebucket.oss-cn-hangzhou.aliyuncs.com/example/example.jpg
      內網訪問URL(供同地區ECS執行個體訪問):https://examplebucket.oss-cn-hangzhou-internal.aliyuncs.com/example/example.jpg
    • 如果您的Bucket綁定了自訂網域名,則檔案URL的格式為https://YourDomainName/ObjectName。更多資訊,請參見綁定自訂網域名至Bucket預設網域名稱

      例如,您在華東1(杭州)地區下的examplebucket綁定了自訂網域名example.com,且該Bucket下包含example.jpg的檔案,則該檔案URL為https://example.com/example.jpg
  1. CDN加速OSS資源:保持 OSS 檔案的許可權為私人,通過 CDN 提供公用讀取訪問。在這種情況下,檔案的 URL 將沒有有效期間,任何人都可以訪問,此時您可以通過CDN加速網域名稱+檔案 URL的方式訪問OSS資源。為了防止檔案被其他網站盜用,建議您在 CDN 配置Referer黑/白名單

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

如何配置訪問OSS檔案是預覽行為?

如果您希望第三方通過URL訪問檔案是預覽效果而非直接下載,請先綁定自訂網域名。如何綁定並使用自訂網域名,請參見綁定自訂網域名至Bucket預設網域名稱

是否可以僅允許指定網站訪問OSS資源,拒絕其他來源的請求?

是的,您可以通過配置Referer防盜鏈,設定白名單,限制只有通過特定網站(如您的網站)才能訪問OSS資源,從而防止其他惡意來源未通過您的網站而直接引用您的OSS檔案。詳細配置步驟,請參見配置Referer防盜鏈來阻止其他網站引用OSS檔案

如何授權第三方對OSS資源進行更多操作,而不僅限於下載?

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

如何自訂下載時的檔案名稱?

可以,您可以通過預簽名URL的response-content-disposition參數來指定某檔案單次下載請求的檔案名稱,或修改檔案的Content-Disposition中繼資料來指定某檔案所有下載請求的檔案名稱。詳情請參見自訂OSS下載檔案時的檔案名稱

如何使用簽名URL對圖片進行處理?

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