全部产品
Search
文档中心

对象存储 OSS:使用预签名URL下载或预览文件

更新时间:Jul 08, 2025

OSS文件默认为私有权限,只有文件拥有者可访问。但文件拥有者可以生成分享链接(预签名URL),授权他人在有效期内下载或在线预览指定文件。

image

工作原理

预签名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

  • <BucketName>:存储空间名称。

  • <ObjectName>:文件的完整路径(如folder/example.jpg)。

  • <Endpoint>:所在地域的访问域名

  • <YourDomainName>:您的自定义域名。更多信息请参见绑定自定义域名至Bucket默认域名

  • <CDN 加速域名>:您的CDN加速域名。

配置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来处理图片,例如调整大小,添加水印等。