生成预签名 URL

最近更新时间:2024-08-13 16:19:52

我的收藏

简介

本文档提供关于生成对象预签名链接的示例代码。
关于使用预签名 URL 上传的说明请参见 预签名授权上传, 使用预签名 URL 下载的说明请参见 预签名授权下载

注意事项

2024年1月1日后创建的桶 不支持使用默认域名在浏览器预览文件,建议您配置自定义域名,详情请参见 存储桶切换自定义域名
使用临时密钥生成预签名,通过临时授权的方式进一步提高预签名上传、下载等请求的安全性。申请临时密钥时,请遵循 最小权限指引原则,防止泄露目标存储桶或对象之外的资源。
如果您一定要使用永久密钥来生成预签名,建议永久密钥的权限范围仅限于上传或下载操作,以规避风险。
由于访问 CDN 域名需要遵循 CDN 的鉴权过程,无法使用 COS 签名,因此预签名 URL 不支持使用 CDN 域名。
使用永久密钥来生成预签名,注意权限范围仅限于上传或下载操作,并且所生成的签名有效时长设置为完成本次上传或下载操作所需的最短期限。
仅支持对单个对象进行预签名,不支持多个对象。
使用预签名 URL 上传时,最大支持上传 5GB 文件。

相关示例

功能名称
描述
示例代码
生成上传预签名链接
提供了生成上传预签名链接的功能。
生成下载预签名链接
提供了生成下载预签名链接的功能。

使用案例

生成预签名上传链接

Objective-C
Swift
1.生成用于上传的签名URL
QCloudGetPresignedURLRequest* getPresignedURLRequest = [[QCloudGetPresignedURLRequest alloc] init];
// 存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucket
getPresignedURLRequest.bucket = @"examplebucket-1250000000";
// 使用预签名 URL 请求的 HTTP 方法。有效值(大小写敏感)为:@"GET"、@"PUT"、@"POST"、@"DELETE"
getPresignedURLRequest.HTTPMethod = @"GET";
// 获取预签名函数,默认签入Header Host;您也可以选择不签入Header Host,但可能导致请求失败或安全漏洞
getPresignedURLRequest.signHost = YES;
// http 请求参数,传入的请求参数需与实际请求相同,能够防止用户篡改此HTTP请求的参数
[getPresignedURLRequest setValue:@"value1" forRequestParameter:@"param1"];
[getPresignedURLRequest setValue:@"value2" forRequestParameter:@"param2"];

// http 请求头部,传入的请求头部需包含在实际请求中,能够防止用户篡改签入此处的HTTP请求头部
[getPresignedURLRequest setValue:@"value1" forRequestHeader:@"param1"];
[getPresignedURLRequest setValue:@"value2" forRequestHeader:@"param2"];
// 对象键,是对象在 COS 上的完整路径,如果带目录的话,格式为 "video/xxx/movie.mp4"
getPresignedURLRequest.object = @"exampleobject";
[getPresignedURLRequest setFinishBlock:^(QCloudGetPresignedURLResult * _Nonnull result,
NSError * _Nonnull error) {
// 预签名 URL
NSString* presignedURL = result.presienedURL;
}];
[[QCloudCOSXMLService defaultCOSXML] getPresignedURL:getPresignedURLRequest];
2.通过签名URL上传文件。
-(void)upload{
// 预签名 URL
NSString* presignedURL = result.presienedURL;
[self uploadFile:presignedURL retryCount:0];
}

-(void)uploadFile:(NSString *)presignedURL retryCount:(NSInteger)retryCount{
// 使用预签名链接进行上传文件
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:presignedURL]];
// 指定HTTPMethod 为PUT
request.HTTPMethod = @"PUT";
// fromData 为需要上传的文件
[[[NSURLSession sharedSession]
uploadTaskWithRequest:request fromData:[@"testtest" dataUsingEncoding:NSUTF8StringEncoding] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (error && ([self isNetworkErrorAndRecoverable:error] || error.code >= 500) && retryCount == 0) {
[self uploadFile:presignedURL retryCount:retryCount + 1];
}
// response中查看上传结果
}]resume];
}

- (BOOL)isNetworkErrorAndRecoverable:(NSError *)error {
if ([error.domain isEqualToString:NSURLErrorDomain]) {
switch (error.code) {
case NSURLErrorCancelled:
case NSURLErrorBadURL:
case NSURLErrorNotConnectedToInternet:
case NSURLErrorSecureConnectionFailed:
case NSURLErrorServerCertificateHasBadDate:
case NSURLErrorServerCertificateUntrusted:
case NSURLErrorServerCertificateHasUnknownRoot:
case NSURLErrorServerCertificateNotYetValid:
case NSURLErrorClientCertificateRejected:
case NSURLErrorClientCertificateRequired:
case NSURLErrorCannotLoadFromNetwork:
return NO;
case NSURLErrorCannotConnectToHost:
default:
return YES;
}
}
if (error.userInfo && error.userInfo[@"Code"]) {
NSString *serverCode = error.userInfo[@"Code"];
if ([serverCode isEqualToString:@"InvalidDigest"] || [serverCode isEqualToString:@"BadDigest"] ||
[serverCode isEqualToString:@"InvalidSHA1Digest"] || [serverCode isEqualToString:@"RequestTimeOut"]) {
return YES;
}
}
return NO;
}
1.生成用于上传的签名URL
let getPresign = QCloudGetPresignedURLRequest.init();

// 存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucket
getPresign.bucket = "examplebucket-1250000000" ;

// 使用预签名 URL 请求的 HTTP 方法。有效值(大小写敏感)为:
// @"GET"、@"PUT"、@"POST"、@"DELETE"
getPresign.httpMethod = "PUT";

// 获取预签名函数,默认签入Header Host;您也可以选择不签入Header Host,但可能导致请求失败或安全漏洞
getPresign.signHost = YES;

// http 请求参数,传入的请求参数需与实际请求相同,能够防止用户篡改此HTTP请求的参数
getPresign.setValue("value1", forRequestParameter: "param1")
getPresign.setValue("value2", forRequestParameter: "param2")


// http 请求头部,传入的请求头部需包含在实际请求中,能够防止用户篡改签入此处的HTTP请求头部
getPresign.setValue("value1", forRequestHeader: "param1")
getPresign.setValue("value2", forRequestHeader: "param2")

// 对象键,是对象在 COS 上的完整路径,如果带目录的话,格式为 "video/xxx/movie.mp4"
getPresign.object = "exampleobject";
getPresign.setFinish { (result, error) in
if let result = result {
// 预签名 URL
let url = result.presienedURL
} else {
print(error!);
}
}
QCloudCOSXMLService.defaultCOSXML().getPresignedURL(getPresign);
2.通过签名URL上传文件。
func upload() {
// 预签名 URL
let presignedURL = "";//result.presignedURL
uploadFile(presignedURL: presignedURL, retryCount: 0)
}
func uploadFile(presignedURL: String, retryCount: Int) {
// 使用预签名链接进行上传文件
guard let url = URL(string: presignedURL) else {
print("Invalid URL")
return
}
var request = URLRequest(url: url)
// 指定HTTPMethod 为PUT
request.httpMethod = "PUT"
// fromData 为需要上传的文件
let dataToUpload = "testtest".data(using: .utf8)!
let task = URLSession.shared.uploadTask(with: request, from: dataToUpload) { data, response, error in
if let error = error {
if (self.isNetworkErrorAndRecoverable(error as NSError) || (error as NSError).code >= 500) && retryCount == 0 {
self.uploadFile(presignedURL: presignedURL, retryCount: retryCount + 1)
}
}
// 在 response 中查看上传结果
if let httpResponse = response as? HTTPURLResponse {
print("Upload completed with status code: \\(httpResponse.statusCode)")
}
}
task.resume()
}

func isNetworkErrorAndRecoverable(_ error: NSError) -> Bool {
if error.domain == NSURLErrorDomain {
switch error.code {
case NSURLErrorCancelled,
NSURLErrorBadURL,
NSURLErrorNotConnectedToInternet,
NSURLErrorSecureConnectionFailed,
NSURLErrorServerCertificateHasBadDate,
NSURLErrorServerCertificateUntrusted,
NSURLErrorServerCertificateHasUnknownRoot,
NSURLErrorServerCertificateNotYetValid,
NSURLErrorClientCertificateRejected,
NSURLErrorClientCertificateRequired,
NSURLErrorCannotLoadFromNetwork:
return false
case NSURLErrorCannotConnectToHost:
fallthrough
default:
return true
}
}

if let userInfo = error.userInfo as? [String: Any],
let serverCode = userInfo["Code"] as? String {
if serverCode == "InvalidDigest" || serverCode == "BadDigest" ||
serverCode == "InvalidSHA1Digest" || serverCode == "RequestTimeOut" {
return true
}
}
return false
}

生成预签名下载链接

Objective-C
Swift
1.生成用于下载的签名 URL
QCloudGetPresignedURLRequest* getPresignedURLRequest = [[QCloudGetPresignedURLRequest alloc] init];

// 存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucket
getPresignedURLRequest.bucket = @"examplebucket-1250000000";

// 使用预签名 URL 请求的 HTTP 方法。有效值(大小写敏感)为:@"GET"、@"PUT"、@"POST"、@"DELETE"
getPresignedURLRequest.HTTPMethod = @"GET";

// 获取预签名函数,默认签入Header Host;您也可以选择不签入Header Host,但可能导致请求失败或安全漏洞
getPresignedURLRequest.signHost = YES;

// http 请求参数,传入的请求参数需与实际请求相同,能够防止用户篡改此HTTP请求的参数
[getPresignedURLRequest setValue:@"value1" forRequestParameter:@"param1"];
[getPresignedURLRequest setValue:@"value2" forRequestParameter:@"param2"];

// http 请求头部,传入的请求头部需包含在实际请求中,能够防止用户篡改签入此处的HTTP请求头部
[getPresignedURLRequest setValue:@"value1" forRequestHeader:@"param1"];
[getPresignedURLRequest setValue:@"value2" forRequestHeader:@"param2"];

// 对象键,是对象在 COS 上的完整路径,如果带目录的话,格式为 "video/xxx/movie.mp4"
getPresignedURLRequest.object = @"exampleobject";

[getPresignedURLRequest setFinishBlock:^(QCloudGetPresignedURLResult * _Nonnull result,
NSError * _Nonnull error) {
// 预签名 URL
NSString* presignedURL = result.presienedURL;
}];

[[QCloudCOSXMLService defaultCOSXML] getPresignedURL:getPresignedURLRequest];
2.通过签名 URL 下载文件。
-(void)download{
// 预签名 URL
NSString* presignedURL = result.presienedURL;
[self downloadFile:presignedURL retryCount:0];
}

-(void)downloadFile:(NSString *)presignedURL retryCount:(NSInteger)retryCount{
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:presignedURL]];
// 指定HTTPMethod为GET
request.HTTPMethod = @"GET";
[[[NSURLSession sharedSession] downloadTaskWithRequest:request completionHandler:^(NSURL *_Nullable location, NSURLResponse *_Nullable response, NSError *_Nullable error) {
// location 下载成功后的本地文件路径
}] resume];
}

- (BOOL)isNetworkErrorAndRecoverable:(NSError *)error {
if ([error.domain isEqualToString:NSURLErrorDomain]) {
switch (error.code) {
case NSURLErrorCancelled:
case NSURLErrorBadURL:
case NSURLErrorNotConnectedToInternet:
case NSURLErrorSecureConnectionFailed:
case NSURLErrorServerCertificateHasBadDate:
case NSURLErrorServerCertificateUntrusted:
case NSURLErrorServerCertificateHasUnknownRoot:
case NSURLErrorServerCertificateNotYetValid:
case NSURLErrorClientCertificateRejected:
case NSURLErrorClientCertificateRequired:
case NSURLErrorCannotLoadFromNetwork:
return NO;
case NSURLErrorCannotConnectToHost:
default:
return YES;
}
}
if (error.userInfo && error.userInfo[@"Code"]) {
NSString *serverCode = error.userInfo[@"Code"];
if ([serverCode isEqualToString:@"InvalidDigest"] || [serverCode isEqualToString:@"BadDigest"] ||
[serverCode isEqualToString:@"InvalidSHA1Digest"] || [serverCode isEqualToString:@"RequestTimeOut"]) {
return YES;
}
}
return NO;
}
1.生成用于下载的签名 URL
let getPresignedURLRequest = QCloudGetPresignedURLRequest();
// 存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.cloud.tencent.com/cos5/bucket
getPresignedURLRequest.bucket = "examplebucket-1250000000";

// 使用预签名 URL 请求的 HTTP 方法。有效值(大小写敏感)为:@"GET"、@"PUT"、@"POST"、@"DELETE"
getPresignedURLRequest.httpMethod = "GET";

// 获取预签名函数,默认签入Header Host;您也可以选择不签入Header Host,但可能导致请求失败或安全漏洞
getPresignedURLRequest.signHost = true;

// http 请求参数,传入的请求参数需与实际请求相同,能够防止用户篡改此HTTP请求的参数
getPresignedURLRequest.setValue("value1", forRequestParameter: "param1")
getPresignedURLRequest.setValue("value2", forRequestParameter: "param2")

// http 请求头部,传入的请求头部需包含在实际请求中,能够防止用户篡改签入此处的HTTP请求头部
getPresignedURLRequest.setValue("value1", forRequestHeader: "param1")
getPresignedURLRequest.setValue("value2", forRequestHeader: "param2")

// 对象键,是对象在 COS 上的完整路径,如果带目录的话,格式为 "video/xxx/movie.mp4"
getPresignedURLRequest.object = "exampleobject";
getPresignedURLRequest.setFinish { (result, error) in
if let result = result {
// 预签名 URL
let url = result.presienedURL
} else {
print(error!);
}
}
QCloudCOSXMLService.defaultCOSXML().getPresignedURL(getPresignedURLRequest);
2.通过签名 URL 下载文件。
func download() {
// 预签名 URL
let presignedURL = result.presignedURL
downloadFile(presignedURL: presignedURL, retryCount: 0)
}

func downloadFile(presignedURL: String, retryCount: Int) {
// 使用预签名链接进行下载文件
guard let url = URL(string: presignedURL) else {
print("Invalid URL")
return
}

var request = URLRequest(url: url)
// 指定HTTPMethod为GET
request.httpMethod = "GET"
let task = URLSession.shared.downloadTask(with: request) { location, response, error in
if let error = error {
if (self.isNetworkErrorAndRecoverable(error as NSError) || (error as NSError).code >= 500) && retryCount == 0 {
self.downloadFile(presignedURL: presignedURL, retryCount: retryCount + 1)
}
} else if let location = location {
// location 下载成功后的本地文件路径
print("Downloaded file location: \\(location)")
}
// 在 response 中查看下载结果
if let httpResponse = response as? HTTPURLResponse {
print("Download completed with status code: \\(httpResponse.statusCode)")
}
}
task.resume()
}

func isNetworkErrorAndRecoverable(_ error: NSError) -> Bool {
if error.domain == NSURLErrorDomain {
switch error.code {
case NSURLErrorCancelled,
NSURLErrorBadURL,
NSURLErrorNotConnectedToInternet,
NSURLErrorSecureConnectionFailed,
NSURLErrorServerCertificateHasBadDate,
NSURLErrorServerCertificateUntrusted,
NSURLErrorServerCertificateHasUnknownRoot,
NSURLErrorServerCertificateNotYetValid,
NSURLErrorClientCertificateRejected,
NSURLErrorClientCertificateRequired,
NSURLErrorCannotLoadFromNetwork:
return false
case NSURLErrorCannotConnectToHost:
fallthrough
default:
return true
}
}

if let userInfo = error.userInfo as? [String: Any],
let serverCode = userInfo["Code"] as? String {
if serverCode == "InvalidDigest" || serverCode == "BadDigest" ||
serverCode == "InvalidSHA1Digest" || serverCode == "RequestTimeOut" {
return true
}
}
return false
}

SDK API 参考

SDK 所有接口的具体参数与方法说明,请参考 SDK API