OSS文件默认为私有权限,只有文件拥有者可访问。但文件拥有者可以生成分享链接(预签名URL),授权他人在有效期内下载或在线预览指定文件。
工作原理
预签名URL的生成过程依赖密钥加密和参数拼接,过程如下:
权限校验:您生成预签名URL时需拥有
oss:GetObject
权限,第三方才能通过该预签名URL成功下载/预览文件;本地加密:基于AK/SK对文件路径、过期时间等信息加密计算,得到签名(
x-oss-signature
);附加签名:将签名参数(
x-oss-date
、x-oss-expires
、x-oss-credential
等)作为查询字符串附加到文件URL;形成链接:组成完整的预签名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(®ion, "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控制台
登录OSS管理控制台。
单击Bucket列表,然后单击目标Bucket名称。
在左侧导航栏,选择
。在文件列表页面,单击目标文件名称。
在详情面板的自有域名,选择绑定的自定义域名,其他保持默认值,然后单击复制文件URL。
使用图形化管理工具ossbrowser
ossbrowser支持Object级别的操作与控制台支持的操作类似,请按照ossbrowser界面指引完成获取预签名URL的操作。如何下载ossbrowser,请参见图形化管理工具ossbrowser 2.0(预览版)。
使用自定义域名登录ossbrowser。
获取文件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(®ion, "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"), // 设置为强制下载
})
方式二:统一设置强制下载(通过元数据)
一次设置后,该文件的所有访问都会强制下载。通过修改文件元数据中的Content-Disposition
字段实现。
使用OSS控制台
在OSS管理控制台中,找到目标文件,在该文件详情面板中单击设置文件元数据,将Content-Disposition
设置为attachment
,然后单击确定保存。
除控制台操作外,也可参考管理文件元数据,通过SDK或命令行工具 ossutil 设置该字段。
如您还希望自定义下载时显示的文件名,请参见自定义下载时的文件名。
获取指定版本文件的链接
生成指定版本文件的链接(预签名URL),适用于已启用版本控制的Bucket。
使用OSS控制台
您可以登录OSS管理控制台,进入目标Bucket的文件列表,在页面右上角切换历史版本为显示。
找到目标文件,单击所需历史版本的文件名,在详情页面中即可复制该版本文件的URL。
使用阿里云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);
使用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。
选中目标文件,然后单击下方的导出URL列表。
在弹出的配置面板中,默认参数适用于大多数场景,无需修改即可使用。
单击确定,下载并保存生成的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)的有效期在生成时设定,过后无法修改。链接在有效期内可多次访问,过期后失效。
不同生成方式支持的最大有效期不同,超出上限会导致生成失败或访问异常。
使用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(®ion, "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默认域名 |
| 例如,华东1(杭州)地域下名为examplebucket的Bucket下有名为example的文件夹,文件夹内有个名为example.jpg的文件。
|
自定义域名 |
| 例如,您在华东1(杭州)地域下的examplebucket绑定了自定义域名 |
CDN加速域名 |
| 例如,当CDN加速域名为 |
<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编码方式渲染文件内容,确保内容正确显示。
登录OSS管理控制台。
单击Bucket 列表,然后单击目标Bucket名称。
在左侧导航栏,选择
。在目标Object右侧选择
。在HTTP标准属性区域,将Content-Type设置为text/plain;charset=utf-8。
单击确定。
限制访问来源
通过配置Referer防盗链,只允许指定网站访问 OSS 资源,拒绝其他来源的请求。
例如,只允许来自您的官网https://example.com
的访问请求,其他来源将被拒绝。
授权第三方更多操作
除了预签名URL,阿里云还提供了更灵活的临时授权方式——STS临时访问凭证。如果您希望第三方对OSS的操作不只是下载,还能执行如列举、拷贝等操作,建议您了解并使用STS临时访问凭证,详情请参见使用STS临时访问凭证访问OSS。
处理图片
您可以生成带图片处理参数的预签名URL来处理图片,例如调整大小,添加水印等。