简介
本文介绍对象存储 COS 通过 Android SDK 实现生成对象预签名链接的示例代码和描述。
注意事项
2024年1月1日后创建的桶 不支持使用默认域名在浏览器预览文件,建议您配置自定义域名,详情请参见 存储桶切换自定义域名。
建议用户使用临时密钥生成预签名,通过临时授权的方式进一步提高预签名上传、下载等请求的安全性。申请临时密钥时,请遵循 最小权限指引原则,防止泄露目标存储桶或对象之外的资源。
如果您一定要使用永久密钥来生成预签名,建议永久密钥的权限范围仅限于上传或下载操作,以规避风险。
使用预签名 URL 上传时,最大支持上传 5GB 文件。
生成预签名 URL 默认签入 Header Host;您也可以选择不签入 Header Host,但可能导致请求失败或安全漏洞。
相关示例
功能名称 | 描述 | 示例代码 |
生成预签名 URL | 对象存储(Cloud Object Storage,COS)支持使用预签名 URL 进行对象的上传、下载,原理是将签名嵌入 URL 生成签名链接。 |
前期准备
创建 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) {@Overridepublic RequestBodySerializer getRequestBody()throws CosXmlClientException {//用于计算 put 等需要带上 body 的请求的签名 URLreturn 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/jpegconnection.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");}}