生成预签名 URL

最近更新时间:2024-08-26 15:13:41

我的收藏

简介

本文介绍对象存储 COS 通过 Android SDK 实现生成对象预签名链接的示例代码和描述。

注意事项

2024年1月1日后创建的桶 不支持使用默认域名在浏览器预览文件,建议您配置自定义域名,详情请参见 存储桶切换自定义域名
建议用户使用临时密钥生成预签名,通过临时授权的方式进一步提高预签名上传、下载等请求的安全性。申请临时密钥时,请遵循 最小权限指引原则,防止泄露目标存储桶或对象之外的资源。
如果您一定要使用永久密钥来生成预签名,建议永久密钥的权限范围仅限于上传或下载操作,以规避风险。
使用预签名 URL 上传时,最大支持上传 5GB 文件。
生成预签名 URL 默认签入 Header Host;您也可以选择不签入 Header Host,但可能导致请求失败或安全漏洞。
关于使用预签名 URL 上传的说明请参见 预签名授权上传, 使用预签名 URL 下载的说明请参见 预签名授权下载

相关示例

功能名称
描述
示例代码
生成预签名 URL
对象存储(Cloud Object Storage,COS)支持使用预签名 URL 进行对象的上传、下载,原理是将签名嵌入 URL 生成签名链接。

前期准备

创建 CosXmlService

调用 COS 的接口之前,必须先创建一个 CosXmlService 的实例,详细代码可以参见 创建 CosXmlService

使用案例

生成预签名上传链接并上传对象

try {
//存储桶名称
String bucket = "examplebucket-1250000000";
// 对象在存储桶中的位置标识符,对象键(Key)是对象在存储桶中的唯一标识。详情请参见 [对象键](https://cloud.tencent.com/document/product/436/13324#.E5.AF.B9.E8.B1.A1.E9.94.AE)
// 注意:用户无需对 cosPath 进行编码操作
String cosPath = "exampleobject";
//请求 HTTP 方法
String method = "PUT";
// 本地文件路径 final String localPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath() + "/wechat.png";
PresignedUrlRequest presignedUrlRequest = new PresignedUrlRequest(bucket
, cosPath) {
@Override
public RequestBodySerializer getRequestBody()
throws CosXmlClientException {
//用于计算 put 等需要带上 body 的请求的签名 URL
return RequestBodySerializer.file(null, new File(localPath));
}
};
presignedUrlRequest.setRequestMethod(method);
// 设置签名有效期为 60s,注意这里是签名有效期,您需要自行保证密钥有效期
presignedUrlRequest.setSignKeyTime(60);
// 设置不签名 某header
// presignedUrlRequest.addNoSignHeader("XXX");
// presignedUrlRequest.addNoSignHeader("Content-Length"); // presignedUrlRequest.addNoSignHeader("Content-Type");
// 获取到预签名上传链接
String urlWithSign = cosXmlService.getPresignedURL(presignedUrlRequest);
// 开始上传
new Thread(new Runnable() { @Override public void run() { uploadFile(urlWithSign, localPath); } }).start();
} catch (CosXmlClientException e) {
e.printStackTrace();
}
使用 HttpURLConnection 进行文件上传
public void uploadFile(String targetUrl, String filePath) { int retryCount = 0; boolean success = false; while (!success && retryCount < 3) { HttpURLConnection connection = null; DataOutputStream outputStream = null; FileInputStream fileInputStream = null; try { fileInputStream = new FileInputStream(filePath); URL url = new URL(targetUrl); connection = (HttpURLConnection) url.openConnection(); connection.setDoInput(true); connection.setDoOutput(true); connection.setUseCaches(false); connection.setRequestMethod("PUT");
// 设置网络请求具体的Content-Type,例如image/jpeg
connection.setRequestProperty("Content-Type", "application/octet-stream"); outputStream = new DataOutputStream(connection.getOutputStream()); int bytesRead; byte[] buffer = new byte[8192]; while ((bytesRead = fileInputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, bytesRead); } outputStream.flush(); if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) { if (connection.getResponseCode() >= 500) { retryCount++; continue; } else { throw new RuntimeException("Server returned HTTP " + connection.getResponseCode() + " " + connection.getResponseMessage()); } } success = true; } catch (Exception e) { retryCount++; } finally { try { if (outputStream != null) outputStream.close(); if (fileInputStream != null) fileInputStream.close(); } catch (Exception ignored) { } if (connection != null) connection.disconnect(); } } if (!success) { throw new RuntimeException("Failed to upload file after 3 attempts"); } }

生成预签名下载链接并下载对象

try {
//存储桶名称
String bucket = "examplebucket-1250000000";
// 对象在存储桶中的位置标识符,对象键(Key)是对象在存储桶中的唯一标识。详情请参见 [对象键](https://cloud.tencent.com/document/product/436/13324#.E5.AF.B9.E8.B1.A1.E9.94.AE)
// 注意:用户无需对 cosPath 进行编码操作
String cosPath = "exampleobject";
//请求 HTTP 方法.
String method = "GET";
PresignedUrlRequest presignedUrlRequest = new PresignedUrlRequest(bucket
, cosPath);
presignedUrlRequest.setRequestMethod(method);

// 设置签名有效期为 60s,注意这里是签名有效期,您需要自行保证密钥有效期
presignedUrlRequest.setSignKeyTime(60);
// 设置不签名 某header
// presignedUrlRequest.addNoSignHeader("XXX");
// presignedUrlRequest.addNoSignHeader("Content-Length"); // presignedUrlRequest.addNoSignHeader("Content-Type");

// 获取到预签名下载链接
String urlWithSign = cosXmlService.getPresignedURL(presignedUrlRequest);
// 开始下载
new Thread(new Runnable() { @Override public void run() { String localPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath() + "/wechat.png"; downloadFile(urlWithSign, localPath); } }).start();
} catch (CosXmlClientException e) {
e.printStackTrace();
}
使用 HttpURLConnection 进行文件下载
public void downloadFile(String fileUrl, String localPath) {
int retryCount = 0;
boolean success = false;
while (!success && retryCount < 3) {
HttpURLConnection connection = null;
InputStream input = null;
FileOutputStream output = null;
try {
URL url = new URL(fileUrl);
connection = (HttpURLConnection) url.openConnection();
connection.connect();
if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
if (connection.getResponseCode() >= 500) {
retryCount++;
continue;
} else {
throw new RuntimeException("Server returned HTTP " + connection.getResponseCode()
+ " " + connection.getResponseMessage());
}
}
input = connection.getInputStream();
output = new FileOutputStream(localPath);
byte data[] = new byte[4096];
int count;
while ((count = input.read(data)) != -1) {
output.write(data, 0, count);
}
success = true;
} catch (Exception e) {
retryCount++;
} finally {
try {
if (output != null)
output.close();
if (input != null)
input.close();
} catch (Exception ignored) {
}
if (connection != null)
connection.disconnect();
}
}
if (!success) {
throw new RuntimeException("Failed to download file after 3 attempts");
}
}

SDK API 参考

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