默认情况下,OSS存储空间中文件的读写权限是私有,仅文件拥有者具有访问文件的权限。但是,文件拥有者可以通过创建签名URL的方式与第三方用户分享文件,签名URL使用安全凭证的方式授权第三方用户在指定时间内下载或者预览文件。
注意事项
生成签名URL过程中,SDK利用本地存储的密钥信息,根据特定算法计算出签名(signature),然后将其附加到URL上,以确保URL的有效性和安全性。这一系列计算和构造URL的操作都是在客户端完成,不涉及网络请求到服务端。因此,生成签名URL时不需要授予调用者特定权限。但是,为避免第三方用户无法对签名URL授权的资源执行相关操作,需要确保调用生成签名URL接口的身份主体被授予对应的权限。
例如,通过签名URL下载或预览文件时,需要授予
oss:GetObject
权限。如需确保通过文件URL访问文件时是预览行为,您需要绑定自定义域名并添加CNAME记录。详情请参见绑定自定义域名至Bucket默认域名。
获取私有文件URL时涉及设置URL的有效时长。超出文件URL设置的有效时长后,通过文件URL访问时会提示签名URL已过期,导致无法正常访问文件。如果您希望继续访问该文件,需要选择以下任意方式重新获取签名URL。
获取单个文件的URL
私有文件
如果文件读写权限ACL为私有,则必须进行签名操作。私有文件URL的格式为https://BucketName.Endpoint/Object?签名参数
。您可以通过以下任意方法获取文件URL并设置URL的有效时长。
文件URL的有效时长因账号类型存在差异。例如,阿里云账号通过OSS控制台可设置的文件URL有效时长最大为32400秒(9小时),RAM用户以及STS用户可设置的文件URL有效时长最大为3600秒(1小时)。如需获取更长时效的文件URL,请使用命令行工具ossutil、图形化管理工具ossbrowser或阿里云SDK。更多信息,请参见私有文件签名URL有效时长。
使用OSS控制台
您可以通过OSS控制台获取单个文件的URL。
登录OSS管理控制台。
单击Bucket列表,然后单击目标Bucket名称。
在左侧导航栏,选择
。获取文件URL。
单击目标文件名称。
在详情面板配置以下参数,然后单击复制文件 URL。
参数
说明
过期时间
当目标文件为私有文件时,需设置文件URL的有效时间。
取值范围:60~32400
单位:秒
如果您希望设置更长过期时间的文件URL,您可以使用ossbrowser、sdk、ossutil等工具。
自有域名
如需确保第三方访问图片或网页文件时是预览行为,请使用Bucket绑定的自定义域名生成文件URL。
仅当Bucket绑定自定义域名后可配置此项。更多信息,请参见绑定自定义域名。
使用HTTPS
默认使用HTTPS协议生成文件URL。如需使用HTTP协议生成文件URL,请关闭使用HTTPS开关。
使用图形化管理工具ossbrowser
ossbrowser支持Object级别的操作与控制台支持的操作类似,请按照ossbrowser界面指引完成获取签名URL的操作。关于如何使用ossbrowser,请参见快速使用ossbrowser。
使用阿里云SDK
以下仅列举常见SDK的生成签名URL并使用签名URL下载文件的代码示例。关于其他SDK的生成签名URL并使用签名URL下载文件的代码示例,请参见SDK简介。
Java
生成下载文件的签名URL。
import com.aliyun.oss.*; import com.aliyun.oss.common.auth.*; 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 { // 以华东1(杭州)的外网Endpoint为例,其它Region请按实际情况填写。 String endpoint = "https://oss-cn-hangzhou.aliyuncs.com"; // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。 EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider(); // 填写Bucket名称,例如examplebucket。 String bucketName = "examplebucket"; // 填写Object完整路径,例如exampleobject.txt。Object完整路径中不能包含Bucket名称。 String objectName = "exampleobject.txt"; // 创建OSSClient实例。 OSS ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider); URL signedUrl = null; try { // 指定生成的签名URL过期时间,单位为毫秒。本示例以设置过期时间为1小时为例。 Date expiration = new Date(new Date().getTime() + 3600 * 1000L); // 生成签名URL。 GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucketName, objectName, HttpMethod.GET); // 设置过期时间。 request.setExpiration(expiration); // 通过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()); } } }
使用签名URL下载文件。
import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import java.io.*; import java.util.*; public class Get1 { public static void main(String[] args) throws Throwable { // 填写下载到本地文件的完整路径。 String pathName = "D:\\example.jpg"; // 填写步骤1生成的签名URL。 String signedUrl= "yourSignedUrl"; Map<String, String> headers = new HashMap<String, String>(); Map<String, String> userMetadata = new HashMap<String, String>(); // 通过签名URL下载文件,以HttpClients为例说明。 getObjectWithHttp(signedUrl, pathName, headers, userMetadata); } public static void getObjectWithHttp(String signedUrl, String pathName, Map<String, String> headers, Map<String, String> userMetadata) throws IOException { CloseableHttpClient httpClient = null; CloseableHttpResponse response = null; try { HttpGet get = new HttpGet(signedUrl); // 如果生成签名URL时设置了header参数,例如用户元数据,存储类型等,则调用签名URL下载文件时,也需要将这些参数发送至服务端。如果签名和发送至服务端的不一致,会报签名错误。 for(Map.Entry header: headers.entrySet()){ get.addHeader(header.getKey().toString(),header.getValue().toString()); } for(Map.Entry meta: userMetadata.entrySet()){ // 如果使用userMeta,sdk内部会为userMeta拼接"x-oss-meta-"前缀。当您使用其他方式生成签名URL进行下载时,userMeta也需要拼接"x-oss-meta-"前缀。 get.addHeader("x-oss-meta-"+meta.getKey().toString(), meta.getValue().toString()); } httpClient = HttpClients.createDefault(); response = httpClient.execute(get); System.out.println("返回下载状态码:"+response.getStatusLine().getStatusCode()); if(response.getStatusLine().getStatusCode() == 200){ System.out.println("使用网络库下载成功"); } System.out.println(response.toString()); saveFileToLocally(response.getEntity().getContent(), pathName); } catch (Exception e){ e.printStackTrace(); } finally { response.close(); httpClient.close(); } } public static void saveFileToLocally(InputStream inputStream, String pathName) throws IOException { DataInputStream in = null; OutputStream out = null; try { in = new DataInputStream(inputStream); out = new DataOutputStream(new FileOutputStream(pathName)); int bytes = 0; byte[] bufferOut = new byte[1024]; while ((bytes = in.read(bufferOut)) != -1) { out.write(bufferOut, 0, bytes); } } catch (Exception e){ e.printStackTrace(); } finally { in.close(); out.close(); } } }
PHP
生成下载文件的签名URL。
<?php if (is_file(__DIR__ . '/../autoload.php')) { require_once __DIR__ . '/../autoload.php'; } if (is_file(__DIR__ . '/../vendor/autoload.php')) { require_once __DIR__ . '/../vendor/autoload.php'; } use OSS\Credentials\EnvironmentVariableCredentialsProvider; use OSS\OssClient; use OSS\Core\OssException; use OSS\Http\RequestCore; use OSS\Http\ResponseCore; // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。 $provider = new EnvironmentVariableCredentialsProvider(); // yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。 $endpoint = "https://oss-cn-hangzhou.aliyuncs.com"; // 填写Bucket名称,例如examplebucket。 $bucket= "examplebucket"; // 填写不包含Bucket名称在内的Object完整路径。 $object = "exampleobject.txt"; // 设置签名URL的有效时长为3600秒。 $timeout = 3600; // 生成下载的签名URL。 $options = array( "response-content-disposition"=>"attachment", ); try { $config = array( "provider" => $provider, "endpoint" => $endpoint, ); $ossClient = new OssClient($config); $signedUrl = $ossClient->signUrl($bucket, $object, $timeout,'GET',$options); } catch (OssException $e) { printf(__FUNCTION__ . ": FAILED\n"); printf($e->getMessage() . "\n"); return; } print(__FUNCTION__ . ": signedUrl: " . $signedUrl . "\n");
使用签名URL下载文件。
<?php if (is_file(__DIR__ . '/../autoload.php')) { require_once __DIR__ . '/../autoload.php'; } if (is_file(__DIR__ . '/../vendor/autoload.php')) { require_once __DIR__ . '/../vendor/autoload.php'; } use OSS\Http\RequestCore; use OSS\Http\ResponseCore; // 填写步骤1生成的签名URL。 $signedUrl = 'yourSignedUrl'; // 填写下载到本地文件的完整路径。 $localfile = "D://example.txt"; // 使用签名URL下载文件。 $request = new RequestCore($signedUrl); // 生成的签名URL默认以GET方式访问。 $request->set_method('GET'); $request->add_header('Content-Type', ''); $request->send_request(); $res = new ResponseCore($request->get_response_header(), $request->get_response_body(), $request->get_response_code()); if ($res->isOK()) { print(__FUNCTION__ . ": OK" . "\n"); file_put_contents($localfile,$request->get_response_body()); } else { print(__FUNCTION__ . ": FAILED" . "\n"); };
Node.js
生成下载文件的签名URL。
const OSS = require("ali-oss"); const client = new OSS({ // yourRegion填写Bucket所在地域。以华东1(杭州)为例,yourRegion填写为oss-cn-hangzhou。 region: "oss-cn-hangzhou", // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。 accessKeyId: process.env.OSS_ACCESS_KEY_ID, accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET, // 填写Bucket名称,例如examplebucket。 bucket: "examplebucket", }); // 生成用于下载文件的签名URL,并指定签名URL的过期时间为3600秒。 const url = client.signatureUrl("exampleobject.txt", { expires: 3600 }); console.log(url);
通过签名URL下载文件。
const axios = require("axios"); const fs = require("fs"); // 填写步骤1生成的签名URL。 const url = "yourSignedUrl"; // 填写下载到本地文件的完整路径。 const file = "D://example.txt"; axios // 设置响应类型为arraybuffer。 .get(url, { responseType: "arraybuffer" }) .then((response) => { fs.writeFile(file, response.data, (err) => { if (err) { console.log(err); } else { console.log("文件下载成功"); } }); }) .catch((error) => { console.log(error); });
Python
生成下载文件的签名URL。
# -*- coding: utf-8 -*- import oss2 from oss2.credentials import EnvironmentVariableCredentialsProvider import requests # 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。 auth = oss2.ProviderAuth(EnvironmentVariableCredentialsProvider()) # yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。 # 填写Bucket名称,例如examplebucket。 bucket = oss2.Bucket(auth, 'https://oss-cn-hangzhou.aliyuncs.com', 'examplebucket') # 填写Object完整路径,例如exampledir/exampleobject.txt。Object完整路径中不能包含Bucket名称。 object_name = 'exampleobject.txt' # 生成下载文件的签名URL,有效时间为3600秒。 # 设置slash_safe为True,OSS不会对Object完整路径中的正斜线(/)进行转义,此时生成的签名URL可以直接使用。 url = bucket.sign_url('GET', object_name, 3600, slash_safe=True) print('签名URL的地址为:', url)
通过签名URL下载文件。
# -*- coding: utf-8 -*- import oss2 import requests # 填写步骤1生成的签名URL。 url = 'yourSignedUrl' # 通过签名URL下载文件,以requests为例说明。 resp = requests.get(url) # 填写下载到本地文件的完整路径。 with open("D:\\examplefile.txt", "wb") as code: code.write(resp.content)
Browser.js
生成下载文件的签名URL。
const OSS = require("ali-oss"); const STS = require("ali-oss").STS; // const cors = require("cors"); const stsClient = new STS({ // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。 accessKeyId: process.env.OSS_ACCESS_KEY_ID, accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET, }); // 填写存储空间名称,例如examplebucket。 const bucket = "examplebucket"; // yourRegion填写Bucket所在地域。以华东1(杭州)为例,Region填写为oss-cn-hangzhou。 const region = "oss-cn-hangzhou"; // 指定角色ARN。 const roleArn = "acs:ram::137918634953****:role/ossram"; const getSts = () => { stsClient .assumeRole( roleArn, `{ "Statement": [ { "Effect": "Allow", "Action": "*", "Resource": [ "acs:oss:*:*:examplebucket/*" ] } ] }`, 3000 //指定SecurityToken过期时间,单位为秒。 ) .then((r) => { console.log("send:", r.credentials); const { SecurityToken, AccessKeyId, AccessKeySecret } = r.credentials; const client = new OSS({ bucket, region, accessKeyId: AccessKeyId, accessKeySecret: AccessKeySecret, stsToken: SecurityToken, refreshSTSTokenInterval: 9000, }); // 生成下载文件的签名URL。 const url = client.asyncSignatureUrl("exampleobject.txt", { expires: 3600, method: "GET", }); console.log("url:", url); // client.get("exampleobject.txt", Buffer.from("body")).then((res) => { // console.log("res", res.url); // }); }); }; getSts();
使用签名URL下载文件。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <title>Document</title> </head> <body> <script src="https://gosspublic.alicdn.com/aliyun-oss-sdk-6.18.0.min.js"></script> <script> // 填写步骤1生成的签名URL。 const url = "yourSignedUrl"; var xhr = new XMLHttpRequest(); xhr.open("GET", url, true); // 设置响应类型为blob。 xhr.responseType = "blob"; xhr.onload = function () { if (xhr.status === 200) { const blob = xhr.response; const reader = new FileReader(); reader.onloadend = function () { const fileData = reader.result; // 自定义下载到本地文件的名称。 const file = new File([fileData], "examplefile.txt"); const a = document.createElement("a"); a.href = URL.createObjectURL(file); a.download = file.name; a.click(); }; reader.readAsArrayBuffer(blob); } else { console.log("请求失败"); } }; xhr.send(); </script> </body> </html>
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(); }
通过签名URL下载文件。
// 填写生成的签名URL。 String url = ""; OkHttpClient client = new OkHttpClient(); // 通过签名URL下载文件。 Request getRequest = new Request.Builder() .url(url) .get() .build(); client.newCall(getRequest).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { e.printStackTrace(); } @Override public void onResponse(Call call, Response response) throws IOException { if (response.code() == 203 || response.code() >= 300) { Log.d("download", "fail"); Log.d("download", response.body().string()); return; } // 请求成功。 InputStream inputStream = response.body().byteStream(); byte[] buffer = new byte[2048]; int len; while ((len = inputStream.read(buffer)) != -1) { // 处理下载的数据,例如图片展示或者写入文件等。 } } });
Go
生成下载文件的签名URL。
package main import ( "fmt" "github.com/aliyun/aliyun-oss-go-sdk/oss" "os" ) func HandleError(err error) { fmt.Println("Error:", err) os.Exit(-1) } func main() { // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。 provider, err := oss.NewEnvironmentVariableCredentialsProvider() if err != nil { fmt.Println("Error:", err) os.Exit(-1) } // 创建OSSClient实例。 // yourEndpoint填写Bucket对应的Endpoint,以华东1(杭州)为例,填写为https://oss-cn-hangzhou.aliyuncs.com。其它Region请按实际情况填写。 client, err := oss.New("yourEndpoint", "", "", oss.SetCredentialsProvider(&provider)) if err != nil { fmt.Println("Error:", err) os.Exit(-1) } // 填写Bucket名称,例如examplebucket。 bucketName := "examplebucket" // 填写文件完整路径,例如exampledir/exampleobject.txt。文件完整路径中不能包含Bucket名称。 objectName := "exampledir/exampleobject.txt" // 将Object下载到本地文件,并保存到指定的本地路径中。如果指定的本地文件存在会覆盖,不存在则新建。 bucket, err := client.Bucket(bucketName) if err != nil { HandleError(err) } // 生成用于下载的签名URL,并指定签名URL的有效时间为60秒。 signedURL, err := bucket.SignURL(objectName, oss.HTTPGet, 60) if err != nil { HandleError(err) } fmt.Printf("Sign Url:%s\n", signedURL) }
使用签名URL下载文件。
package main import ( "fmt" "os" "github.com/aliyun/aliyun-oss-go-sdk/oss" ) func main() { // 创建OSSClient实例。 // yourEndpoint填写Bucket对应的Endpoint,以华东1(杭州)为例,填写为https://oss-cn-hangzhou.aliyuncs.com。其它Region请按实际情况填写。 client, err := oss.New("https://oss-cn-hangzhou.aliyuncs.com", "", "") if err != nil { fmt.Println("Error:", err) os.Exit(-1) } // 填写Bucket名称,例如examplebucket。 bucketName := "examplebucket" // 填写本地文件完整路径。 localDownloadedFilename := "D://example.txt" bucket, err := client.Bucket(bucketName) if err != nil { HandleError(err) } // 填写步骤1获取的签名URL。 signedURL := "yourSignedUrl" // 使用签名URL将OSS文件下载到本地文件。 err = bucket.GetObjectToFileWithURL(signedURL, localDownloadedFilename) if err != nil { HandleError(err) } } func HandleError(err error) { fmt.Println("Error:", err) os.Exit(-1) }
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; }];
使用签名URL下载文件。
// 使用签名URL下载文件。 NSURL * url = [NSURL URLWithString:urlString]; NSURLRequest * request = [NSURLRequest requestWithURL:url]; NSURLSession * session = [NSURLSession sharedSession]; NSURLSessionTask * sessionTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { if (error) { NSLog(@"download error: %@", error); return; } else if (((NSHTTPURLResponse*)response).statusCode == 203 || ((NSHTTPURLResponse*)response).statusCode >= 300) { NSString *body = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"download error: %@", body); return; } NSLog(@"download success"); }]; [sessionTask resume];
使用命令行工具ossutil
关于使用ossutil生成签名URL的具体操作, 请参见sign(生成签名URL)。
公共读文件
如果文件的读写权限ACL为公共读,即该文件允许匿名访问,则文件URL的格式为https://BucketName.Endpoint/ObjectName
。其中,ObjectName需填写包含文件夹以及文件后缀在内的该文件的完整路径。各地域的Endpoint信息介绍,请参见访问域名和数据中心。
例如华东1(杭州)地域下名为examplebucket的Bucket下有名为example的文件夹,文件夹内有个名为example.jpg的文件。则该文件URL为:
外网访问URL:
https://examplebucket.oss-cn-hangzhou.aliyuncs.com/example/example.jpg
内网访问URL(供同地域ECS实例访问):
https://examplebucket.oss-cn-hangzhou-internal.aliyuncs.com/example/example.jpg
如果文件所在的Bucket绑定了自定义域名,则文件URL的格式为https://YourDomainName/ObjectName
。
例如您在华东1(杭州)地域下的examplebucket绑定了自定义域名example.com
,且该Bucket下包含example.jpg的文件,则该文件URL为https://example.com/example.jpg
。
获取多个文件的URL
仅OSS控制台支持批量获取多个文件的URL。
选中目标文件,然后单击下方的导出URL列表。
在导出URL列表面板,配置以下参数:
参数
说明
使用HTTPS
默认使用HTTPS协议生成文件URL。如需使用HTTP协议生成文件URL,请关闭使用HTTPS开关。
过期时间
当目标文件为私有文件时,需设置文件URL的有效时间。
取值范围:60~32400
单位:秒
若您希望获取更长时效的文件URL,建议使用命令行工具ossutil或图形化工具ossbrowser。
自有域名
如需确保第三方访问图片或网页文件时是预览行为,请使用Bucket绑定的自定义域名生成文件URL。
仅当Bucket绑定自定义域名后可配置此项。更多信息,请参见绑定自定义域名。
传输加速域名
若第三方涉及跨国或跨洋等超远距离文件访问场景时,建议使用传输加速域名生成文件URL。
仅当Bucket开启传输加速后可配置此项。更多信息,请参见开启传输加速。
单击确定,然后将URL列表文件保存到本地。
如果您希望通过命令行管理工具ossutil、阿里云SDK批量获取多个文件的URL时:
通过GetBucket (ListObjects)接口获取所有Object的名称。
循环调用获取单个文件的URL方法。具体操作,请参见获取单个文件的URL。
相关文档
您可以上传ECS的镜像文件至OSS,然后获取镜像文件URL导入自定义镜像。更多信息,请参见上传镜像文件至OSS和导入自定义镜像。