This document describes how to set up a secure temporary key service and how to initialize and upload using the Android SDK.
Solution strengths
Permission security: It can effectively restrict the secure permission scope and only allow uploads to a specified file path.
Path security: The random COS file path is determined by the server, which can effectively avoid the problem of existing files being overwritten and security risks.
Upload Process
1. The client selects the file and sends the original filename to the server.
2. Based on the file name suffix, the server generates a timestamped random COS file path, then applies for a temporary key and cos key with corresponding permissions and returns them to the client.
3. The client uses the advanced upload API to upload files to COS.
Temporary Key Setup
Temporary Keys (Temporary Access Credentials) are credentials with limited permissions obtained through the CAM TencentCloud API. When COS API requests are initiated, three fields returned by the temporary key API are required: TmpSecretId, TmpSecretKey, and Token, which are used to calculate the signature.
The getKeyAndCredentials API returns temporary keys information along with the Bucket, Region, and cosKey required for upload.
The following provides sample code in multiple languages:
// Temporary key service exampleconst STS = require('qcloud-cos-sts');const express = require('express');const pathLib = require('path');// Configuration parametersconst config = {secretId: process.env.SecretId,secretKey: process.env.SecretKey,proxy: process.env.Proxy,durationSeconds: 1800,bucket: process.env.Bucket,region: process.env.Region,// Permissions list for key upload operationsallowActions: [// Simple upload'name/cos:PutObject',// Multipart upload'name/cos:InitiateMultipartUpload','name/cos:ListMultipartUploads','name/cos:ListParts','name/cos:UploadPart','name/cos:CompleteMultipartUpload',],};// Generate the file path and name for the COS uploadconst generateCosKey = function (ext) {const date = new Date();const m = date.getMonth() + 1;const ymd = `${date.getFullYear()}${m < 10 ? `0${m}` : m}${date.getDate()}`;const r = ('000000' + Math.random() * 1000000).slice(-6);const cosKey = `file/${ymd}/${ymd}_${r}${ext ? `${ext}` : ''}`;return cosKey;};// Create a temporary key serviceconst app = express();app.use(function (req, res, next) {res.header('Access-Control-Allow-Origin', '*');res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');next();});// Get temporary keysfunction getSts({ cosKey, condition }) {return new Promise((resolve, reject) => {// Obtain temporary keysconst AppId = config.bucket.substr(config.bucket.lastIndexOf('-') + 1);let resource ='qcs::cos:' +config.region +':uid/' +AppId +':' +config.bucket +'/' +cosKey;console.log('Check if the resource is correct', resource);const policy = {version: '2.0',statement: [{action: config.allowActions,effect: 'allow',resource: [// cos authorization pathresource,// CI-related authorization path, use as needed// 'qcs::ci:' + config.region + ':uid/' + AppId + ':bucket/' + config.bucket + '/' + 'job/*',],condition},],};const startTime = Math.round(Date.now() / 1000);STS.getCredential({secretId: config.secretId,secretKey: config.secretKey,proxy: config.proxy,region: config.region,durationSeconds: config.durationSeconds,// endpoint: 'sts.internal.tencentcloudapi.com', // Supports setting the private network domain for stspolicy: policy,},function (err, tempKeys) {if (tempKeys) tempKeys.startTime = startTime;if (err) {reject(err);} else {resolve(tempKeys);}});});}// Return temporary keys and upload information; the client independently calculates the signatureapp.get('/getKeyAndCredentials', function (req, res, next) {// The business should implement user login status validation, such as token validation// const userToken = req.query.userToken;// const canUpload = checkUserRole(userToken);// if (!canUpload) {// res.send({ error: 'The current user does not have upload permissions' });// return;// }// Upload files; control the types and sizes that can be uploaded, and enable as neededconst permission = {limitExt: false, // Limit uploaded file extensionsextWhiteList: ['jpg', 'jpeg', 'png', 'gif', 'bmp'], // Allowed file extensions// limitContentType: false, // Limit upload content typelimitContentLength: false, // Limit uploaded file size};// The client passes the original filename, and a random Key is generated based on the file extensionconst filename = req.query.filename;if (!filename) {res.send({ error: 'Please provide the file name' });}const ext = pathLib.extname(filename);const cosKey = generateCosKey(ext);const condition = {};// 1. Limit uploaded file extensionsif (permission.limitExt) {const extInvalid = !ext || !extWhiteList.includes(ext);if (extInvalid) {res.send({ error: 'Illegal file, upload prohibited' });}}// 2. Limit uploaded file content-typeif (permission.limitContentType) {Object.assign(condition, {'string_like_if_exist': {// Only allow uploading files with image content-type'cos:content-type': 'image/*'}});}// 3. Limit uploaded file sizeif (permission.limitContentLength) {Object.assign(condition, {'numeric_less_than_equal': {// The upload size limit cannot exceed 5MB (only effective for simple uploads)'cos:content-length': 5 * 1024 * 1024},});}getSts({ cosKey, condition }).then((data) => {res.send(Object.assign(data, {startTime: Math.round(Date.now() / 1000),bucket: config.bucket,region: config.region,key: cosKey,}));}).catch((err) => {console.log('sts error', err);res.send(err);});});app.all('*', function (req, res, next) {res.send({ code: -1, message: '404 Not Found' });});// Start the signature serviceapp.listen(3000);console.log('app is listening at http://127.0.0.1:3000');
package mainimport ("fmt""github.com/tencentyun/qcloud-cos-sts-sdk/go""math/rand""os""time")type Config struct {filename stringappId stringSecretId stringSecretKey stringProxy stringDurationSeconds intBucket stringRegion stringAllowActions []string}type Permission struct {LimitExt bool `json:"limitExt"`ExtWhiteList []string `json:"extWhiteList"`LimitContentType bool `json:"limitContentType"`LimitContentLength bool `json:"limitContentLength"`}func generateCosKey(ext string) string {date := time.Now()m := int(date.Month()) + 1ymd := fmt.Sprintf("%d%02d%d", date.Year(), m, date.Day())r := fmt.Sprintf("%06d", rand.Intn(1000000))cosKey := fmt.Sprintf("file/%s/%s_%s.%s", ymd, ymd, r, ext)return cosKey}func getPermission() Permission {permission := Permission{LimitExt: false,ExtWhiteList: []string{"jpg", "jpeg", "png", "gif", "bmp"},LimitContentType: false,LimitContentLength: false,}return permission}func getConfig() Config {config := Config{filename: "test.jpg",appId: "12500000000",SecretId: os.Getenv("SECRETID"), // User's SecretId. It is recommended to use a sub-account key; authorization follows the principle of least privilege to reduce usage risks. For obtaining sub-account keys, refer to https://cloud.tencent.com/document/product/598/37140SecretKey: os.Getenv("SECRETKEY"), // User's SecretKey. It is recommended to use a sub-account key; authorization follows the principle of least privilege to reduce usage risks. For obtaining sub-account keys, refer to https://cloud.tencent.com/document/product/598/37140Proxy: os.Getenv("Proxy"),DurationSeconds: 1800,Bucket: "bucket-12500000000",Region: "ap-guangzhou",AllowActions: []string{"name/cos:PutObject","name/cos:InitiateMultipartUpload","name/cos:ListMultipartUploads","name/cos:ListParts","name/cos:UploadPart","name/cos:CompleteMultipartUpload",},}return config}func stringInSlice(str string, list []string) bool {for _, v := range list {if v == str {return true}}return false}func StructToCamelMap(input interface{}) map[string]interface{} {v := reflect.ValueOf(input)if v.Kind() == reflect.Ptr {v = v.Elem()}result := make(map[string]interface{})typ := v.Type()for i := 0; i < v.NumField(); i++ {field := typ.Field(i)fieldValue := v.Field(i)// Convert field names to camelCasekey := toLowerCamel(field.Name)// Handle nested structsif fieldValue.Kind() == reflect.Struct ||(fieldValue.Kind() == reflect.Ptr && fieldValue.Elem().Kind() == reflect.Struct) {if fieldValue.IsNil() && fieldValue.Kind() == reflect.Ptr {result[key] = nilcontinue}result[key] = StructToCamelMap(fieldValue.Interface())} else {// Handle basic typesresult[key] = fieldValue.Interface()}}return result}// Convert to camelCase format (first letter lowercase)func toLowerCamel(s string) string {if s == "" {return s}// Handle words in all caps (e.g., ID)if strings.ToUpper(s) == s {return strings.ToLower(s)}// Ordinary camelCase conversionrunes := []rune(s)runes[0] = unicode.ToLower(runes[0])return string(runes)}func main() {config := getConfig()permission := getPermission()c := sts.NewClient(// Obtain the key through environment variables. The os.Getenv method is used to obtain environment variables.config.SecretId, //os.Getenv("SECRETID"), // User's SecretId. It is recommended to use a sub-account key; authorization follows the principle of least privilege to reduce usage risks. For obtaining sub-account keys, refer to https://cloud.tencent.com/document/product/598/37140config.SecretKey, //os.Getenv("SECRETKEY"), // User's SecretKey. It is recommended to use a sub-account key; authorization follows the principle of least privilege to reduce usage risks. For obtaining sub-account keys, refer to https://cloud.tencent.com/document/product/598/37140nil,// sts.Host("sts.internal.tencentcloudapi.com"), // Set the domain. The default domain is sts.tencentcloudapi.com// sts.Scheme("http"), // Set the protocol (defaults to https). In the public cloud, sts does not allow http for obtaining temporary keys; set http only in special scenarios.)condition := make(map[string]map[string]interface{})segments := strings.Split(config.filename, ".")if len(segments) == 0 {//ext := ""}ext := segments[len(segments)-1]if permission.LimitExt {extInvalid := ext == "" || !stringInSlice(ext, permission.ExtWhiteList)if extInvalid {fmt.Printf("%+v\n", "Illegal file, upload prohibited")return}}if permission.LimitContentType {condition["string_like_if_exist"] = map[string]interface{}{// Only allow uploading files with image content-type"cos:content-type": "image/*",}}// 3. Limit uploaded file sizeif permission.LimitContentLength {condition["numeric_less_than_equal"] = map[string]interface{}{// The upload size limit cannot exceed 5MB (only effective for simple uploads)"cos:content-length": 5 * 1024 * 1024,}}key := generateCosKey(ext)// Policy Overview https://cloud.tencent.com/document/product/436/18023opt := &sts.CredentialOptions{DurationSeconds: int64(config.DurationSeconds),Region: config.Region,Policy: &sts.CredentialPolicy{Version: "2.0",Statement: []sts.CredentialPolicyStatement{{// Permissions list for keys. Simple upload and multipart upload require the following permissions. For other permissions, see https://cloud.tencent.com/document/product/436/31923Action: config.AllowActions,Effect: "allow",Resource: []string{// Modify this to the allowed path prefix. You can determine the specific upload path based on the user login status of your website, for example: a.jpg, a/*, or * (using wildcard * poses significant security risks; evaluate its use carefully)// The bucket naming format is BucketName-APPID. The bucket filled in here must follow this format."qcs::cos:ap-guangzhou:uid/" + config.appId + ":" + config.Bucket + "/" + key,},// Start building the condition// For detailed setting rules of condition and the condition types supported by COS, see https://cloud.tencent.com/document/product/436/71306Condition: condition,},},},}// case 1 Request temporary keysres, err := c.GetCredential(opt)if err != nil {panic(err)}// Convert to camelCase mapresultMap := StructToCamelMap(res)resultMap["bucket"] = config.BucketresultMap["region"] = config.RegionresultMap["key"] = key// Print the resultjsonBytes, err := json.MarshalIndent(resultMap, "", " ")if err != nil {panic(err)}// Convert to string and printfmt.Println(string(jsonBytes))}
<?phprequire_once __DIR__ . '/vendor/autoload.php';use QCloud\COSSTS\Sts;// Generate the file path and name for the COS uploadfunction generateCosKey($ext) {$ymd = date('Ymd');$r = substr('000000' . rand(), -6);$cosKey = 'file/' . $ymd. '/' . $ymd . '_' . $r;if ($ext) {$cosKey = $cosKey . '.' . $ext;}return $cosKey;};// Obtain temporary keys for single file upload authorizationfunction getKeyAndCredentials($filename) {// The business should implement user login status validation, such as token validation// $canUpload = checkUserRole($userToken);// if (!$canUpload) {// return 'The current user does not have upload permissions';// }// Upload files; control the types and sizes that can be uploaded, and enable as needed$permission = array('limitExt' => false, // Limit uploaded file extensions'extWhiteList' => ['jpg', 'jpeg', 'png', 'gif', 'bmp'], // Allowed file extensions'limitContentType' => false, // Limit upload content type'limitContentLength' => false, // Limit uploaded file size);$condition = array();// The client passes the original filename, and a random Key is generated based on the file extension$ext = pathinfo($filename, PATHINFO_EXTENSION);// 1. Limit uploaded file extensionsif ($permission['limitExt']) {if ($ext === '' || array_key_exists($ext, $permission['extWhiteList'])) {return 'Illegal file, upload prohibited';}}// 2. Limit uploaded file content-typeif ($permission['limitContentType']) {// Only allow content-type to be image types for upload$condition['string_like_if_exist'] = array('cos:content-type' => 'image/*');}// 3. Limit uploaded file sizeif ($permission['limitContentLength']) {// The upload size limit must not exceed 5MB (applies only to simple uploads)$condition['numeric_less_than_equal'] = array('cos:content-length' => 5 * 1024 * 1024);}$cosKey = generateCosKey($ext);$bucket = 'test-131234567'; // Replace with your bucket$region = 'ap-guangzhou'; // Replace with the region where your bucket is located$config = array('url' => 'https://sts.tencentcloudapi.com/', // The url should be consistent with the domain'domain' => 'sts.tencentcloudapi.com', // Domain name, optional, defaults to sts.tencentcloudapi.com'proxy' => '','secretId' => getenv('GROUP_SECRET_ID'), // Fixed secret key. If it's a plaintext secret key, please directly enter it as 'xxx', do not put it in the getenv() function.'secretKey' => getenv('GROUP_SECRET_KEY'), // Fixed secret key. If it's a plaintext secret key, please directly enter it as 'xxx', do not put it in the getenv() function.'bucket' => $bucket, // Replace with your bucket'region' => $region, // Replace with the region where your bucket is located'durationSeconds' => 1800, // Validity period of the key'allowPrefix' => array($cosKey), // Only grant path permissions for the current key// The list of permissions for the key. The following permissions are required for simple uploads and multipart uploads. For other permission lists, refer to https://cloud.tencent.com/document/product/436/31923'allowActions' => array (// Simple upload'name/cos:PutObject',// Upload in shards.'name/cos:InitiateMultipartUpload','name/cos:ListMultipartUploads','name/cos:ListParts','name/cos:UploadPart','name/cos:CompleteMultipartUpload'),);if (!empty($condition)) {$config['condition'] = $condition;}$sts = new Sts();$tempKeys = $sts->getTempKeys($config);$resTemp = array_merge($tempKeys,['startTime' => time(),'bucket' => $bucket,'region' => $region,'key' => $cosKey,]);echo json_encode($resTemp, JSON_UNESCAPED_SLASHES);return $resTemp;}
#!/usr/bin/env python# coding=utf-8import jsonimport osimport datetimeimport randomfrom sts.sts import Stsif __name__ == '__main__':# Configuration Parametersconfig = {"filename":"test.jpg","appId": "125000000","secretId": os.getenv("SecretId"),"secretKey": os.getenv("SecretKey"),"proxy": os.getenv("Proxy"),"durationSeconds": 1800,"bucket": "bucket-125000000","region": "ap-guangzhou",# Permissions List for Key Upload Operations"allowActions": [# Simple Upload"name/cos:PutObject",# Multipart upload"name/cos:InitiateMultipartUpload","name/cos:ListMultipartUploads","name/cos:ListParts","name/cos:UploadPart","name/cos:CompleteMultipartUpload",],}permission = {"limitExt": False, # Limit uploaded file extensions"extWhiteList": ["jpg", "jpeg", "png", "gif", "bmp"], # Allowed file extensions"limitContentType": False, # Restrict upload content type"limitContentLength": False, # Limit uploaded file size}# Generate the file path and file name for uploading to COSdef generate_cos_key(ext=None):date = datetime.datetime.now()ymd = date.strftime('%Y%m%d')r = str(int(random.random() * 1000000)).zfill(6)cos_key = f"file/{ymd}/{ymd}_{r}.{ext if ext else ''}"return cos_keysegments = config['filename'].split(".")ext = segments[-1] if segments else ""key = generate_cos_key(ext)resource = f"qcs::cos:{config['region']}:uid/{config['appId']}:{config['bucket']}/{key}"condition = {}# 1. Limit uploaded file extensionsif permission["limitExt"]:ext_invalid = not ext or ext not in permission["extWhiteList"]if ext_invalid:print('Illegal file, upload prohibited')# 2. Limit uploaded file content-typeif permission["limitContentType"]:condition.update({"string_like_if_exist": {# Only allow uploading files with image content-type"cos:content-type": "image/*"}})# 3. Limit uploaded file sizeif permission["limitContentLength"]:condition.update({"numeric_less_than_equal": {# The upload size limit cannot exceed 5MB (only effective for simple uploads)"cos:content-length": 5 * 1024 * 1024}})def get_credential_demo():credentialOption = {# Validity period of temporary credentials, in seconds'duration_seconds': config.get('durationSeconds'),'secret_id': config.get("secretId"),# Fixed Key'secret_key': config.get("secretKey"),# Replace with your bucket'bucket': config.get("bucket"),'proxy': config.get("proxy"),# Replace with the region where your bucket is located'region': config.get("region"),"policy": {"version": '2.0',"statement": [{"action": config.get("allowActions"),"effect": "allow","resource": [resource],"condition": condition}],},}try:sts = Sts(credentialOption)response = sts.get_credential()credential_dic = dict(response)credential_info = credential_dic.get("credentials")credential = {"bucket": config.get("bucket"),"region": config.get("region"),"key": key,"startTime": credential_dic.get("startTime"),"expiredTime": credential_dic.get("expiredTime"),"requestId": credential_dic.get("requestId"),"expiration": credential_dic.get("expiration"),"credentials": {"tmpSecretId": credential_info.get("tmpSecretId"),"tmpSecretKey": credential_info.get("tmpSecretKey"),"sessionToken": credential_info.get("sessionToken"),},}print('get data : ' + json.dumps(credential, indent=4))except Exception as e:print(e)get_credential_demo()
package com.tencent.cloud;import com.tencent.cloud.assumerole.AssumeRoleParam;import com.tencent.cloud.cos.util.Jackson;import org.junit.Test;import java.io.File;import java.io.FileInputStream;import java.text.SimpleDateFormat;import java.util.*;public class GetKeyAndCredentialsTest {public static String generateCosKey(String ext) {Date date = new Date();SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");String ymd = dateFormat.format(date);Random random = new Random();int r = random.nextInt(1000000);String rStr = String.format("%06d", r);String cosKey = String.format("file/%s/%s_%s.%s", ymd, ymd, rStr, ext != null ? ext : "");return cosKey;}// Obtain configuration informationpublic TreeMap<String,Object> getConfig(){String bucket = "test-12500000000";String appId = "12500000000";String filename = "test.jpg";String region = "ap-guangzhou";String secretId = "";String secretKey = "";String proxy = "";int durationSeconds = 1800;String[] segments = filename.split("\\.");String ext = segments.length > 0 ? segments[segments.length - 1] : "";// Temporary key limitationsBoolean limitExt = false; // Limit uploaded file extensionsList extWhiteList = Arrays.asList("jpg", "jpeg", "png", "gif", "bmp"); // Allowed file extensionsBoolean limitContentType = false; // Restrict upload content typeBoolean limitContentLength = false; // Limit uploaded file sizeMap<String, Object> condition = new HashMap();// 1. Limit uploaded file extensionsif (limitExt) {boolean extInvalid = ext == null || !extWhiteList.contains(ext);if (extInvalid) {System.out.println("Illegal file, upload prohibited");return null;}}// 2. Limit uploaded file content-typeif (limitContentType) {condition.put("string_like_if_exist", new HashMap<String, String>() {{put("cos:content-type", "image/*");}});}// 3. Limit uploaded file size (applies only to simple uploads)if (limitContentLength) {condition.put("numeric_less_than_equal", new HashMap<String, Long>() {{put("cos:content-length", 5L * 1024 * 1024);}});}String key = generateCosKey(ext);String resource = "qcs::cos:" + region + ":uid/" + appId + ':' + bucket + '/' + key;List allowActions = Arrays.asList(// Simple upload"name/cos:PutObject",// Multipart upload"name/cos:InitiateMultipartUpload","name/cos:ListMultipartUploads","name/cos:ListParts","name/cos:UploadPart","name/cos:CompleteMultipartUpload");// Build policyMap<String, Object> policy = new HashMap();policy.put("version", "2.0");Map<String, Object> statement = new HashMap();statement.put("action", allowActions);statement.put("effect", "allow");List<String> resources = Arrays.asList(resource);statement.put("resource", resources);statement.put("condition", condition);policy.put("statement", Arrays.asList(statement));// Build configTreeMap <String,Object> config = new TreeMap<String, Object>();config.put("secretId",secretId);config.put("secretKey",secretKey);config.put("proxy",proxy);config.put("duration",durationSeconds);config.put("bucket",bucket);config.put("region",region);config.put("key",key);config.put("policy",Jackson.toJsonPrettyString(policy));return config;}/*** Basic example for requesting temporary credentials, which is suitable for granting a set of operations permissions for a batch of object keys within a bucket*/@Testpublic void testGetKeyAndCredentials() {TreeMap config = this.getConfig();try {Response response = CosStsClient.getCredential(config);TreeMap <String,Object> credential = new TreeMap<String, Object>();TreeMap <String,Object> credentials = new TreeMap<String, Object>();credentials.put("tmpSecretId",response.credentials.tmpSecretId);credentials.put("tmpSecretKey",response.credentials.tmpSecretKey);credentials.put("sessionToken",response.credentials.sessionToken);credential.put("startTime",response.startTime);credential.put("expiredTime",response.expiredTime);credential.put("requestId",response.requestId);credential.put("expiration",response.expiration);credential.put("credentials",credentials);credential.put("bucket",config.get("bucket"));credential.put("region",config.get("region"));credential.put("key",config.get("key"));System.out.println(Jackson.toJsonPrettyString(credential));} catch (Exception e) {e.printStackTrace();throw new IllegalArgumentException("no valid secret !");}}}
using System;using System.Collections.Generic;using System.IO;using System.Linq;using System.Reflection;using System.Text;using System.Threading;using System.Threading.Tasks;using System.Net.Mail;using COSSTS;using Newtonsoft.Json;using Formatting = System.Xml.Formatting;namespace COSSnippet{public class GetKeyAndCredentials{// Permanent secret keystring secretId = "";string secretKey = "";string bucket = "bucket-125000000";string appId = "125000000";string region = "ap-guangzhou";string filename = "test.jpg";int time = 1800;// LimitBoolean limitExt = false; // Limit uploaded file extensionsList<string> extWhiteList = new List<String> { "jpg", "jpeg", "png", "gif", "bmp" }; // Allowed file extensionsBoolean limitContentType = false; // Restrict upload content typeBoolean limitContentLength = false; // Limit uploaded file sizepublic string generateCosKey(string ext){DateTime date = DateTime.Now;int m = date.Month;string ymd = $"{date.Year}{(m < 10 ? $"0{m}" : m.ToString())}{date.Day}";Random random = new Random();string r = random.Next(0, 1000000).ToString("D6"); // Generate a 6-digit random number with leading zerosstring cosKey = $"file/{ymd}/{ymd}_{r}.{(string.IsNullOrEmpty(ext) ? "" : ext)}";return cosKey;}public Dictionary<string, object> getConfig(){Dictionary<string, object> config = new Dictionary<string, object>();string[] allowActions = new string[] { // Allowed operations scope, using upload operation as an example"name/cos:PutObject","name/cos:PostObject","name/cos:InitiateMultipartUpload","name/cos:ListMultipartUploads","name/cos:ListParts","name/cos:UploadPart","name/cos:CompleteMultipartUpload",};string[] segments = filename.Split(".");string ext = segments.Length > 0 ? segments[segments.Length - 1] : string.Empty;string key = generateCosKey(ext);string resource = $"qcs::cos:{region}:uid/{appId}:{bucket}/{key}";var condition = new Dictionary<string, object>();// 1. Limit uploaded file extensionsif (limitExt){var extInvalid = string.IsNullOrEmpty(ext) || !extWhiteList.Contains(ext);if (extInvalid){Console.WriteLine("Illegal file, upload prohibited");return null;}}// 2. Limit uploaded file content-typeif (limitContentType){condition["string_like_if_exist"] = new Dictionary<string, string>{{ "cos:content-type", "image/*" } // Only allow uploading files with image content-type};}// 3. Limit uploaded file size (applies only to simple uploads)if (limitContentLength){condition["numeric_less_than_equal"] = new Dictionary<string, long>{{ "cos:content-length", 5 * 1024 * 1024 } // The upload size limit cannot exceed 5MB};}var policy = new Dictionary<string, object>{{ "version", "2.0" },{ "statement", new List<Dictionary<string, object>>{new Dictionary<string, object>{{ "action", allowActions },{ "effect", "allow" },{ "resource", new List<string>{resource,}},{ "condition", condition }}}}};// Serialize to JSON and outputstring jsonPolicy = JsonConvert.SerializeObject(policy);config.Add("bucket", bucket);config.Add("region", region);config.Add("durationSeconds", time);config.Add("secretId", secretId);config.Add("secretKey", secretKey);config.Add("key", key);config.Add("policy", jsonPolicy);return config;}// obtain federated identity temporary access credentials https://cloud.tencent.com/document/product/1312/48195public Dictionary<string, object> GetCredential(){var config = getConfig();// Obtain temporary keysDictionary<string, object> credential = STSClient.genCredential(config);Dictionary<string, object> credentials = JsonConvert.DeserializeObject<Dictionary<string, object>>(JsonConvert.SerializeObject((object) credential["Credentials"]));Dictionary<string, object> credentials1 = new Dictionary<string, object>();credentials1.Add("tmpSecretId",credentials["TmpSecretId"]);credentials1.Add("tmpSecretKey",credentials["TmpSecretKey"]);credentials1.Add("sessionToken",credentials["Token"]);Dictionary<string, object> dictionary1 = new Dictionary<string, object>();dictionary1.Add("credentials",credentials1);dictionary1.Add("startTime",credential["StartTime"]);dictionary1.Add("requestId",credential["RequestId"]);dictionary1.Add("expiration",credential["Expiration"]);dictionary1.Add("expiredTime",credential["ExpiredTime"]);dictionary1.Add("bucket",config["bucket"]);dictionary1.Add("region",config["region"]);dictionary1.Add("key",config["key"]);return dictionary1;}static void Main(string[] args){GetKeyAndCredentials m = new GetKeyAndCredentials();Dictionary<string, object> result = m.GetCredential();string Credentials = JsonConvert.SerializeObject(result);Console.WriteLine($"{Credentials}");}}}
Client Initiates Upload
// Assume that the local path of the file to be uploaded is filePathString filePath = "/path/to/your/file.txt";// 1. Request upload and signature information from the serverFile file = new File(filePath);// The getKeyAndCredentials method is in the next code blockJSONObject keyAndCredentials = getKeyAndCredentials(file.getName());String region = keyAndCredentials.getString("region");String bucket = keyAndCredentials.getString("bucket");String cosKey = keyAndCredentials.getString("key");long startTime = keyAndCredentials.getLong("startTime");// Example 1 for obtaining temporary keys: If obtaining temporary keys through qcloud-cos-sts-sdk, the structure of the returned fields. Retrieve temporary key information and file path details for upload from the responselong expiredTime = keyAndCredentials.getLong("expiredTime");JSONObject credentials = keyAndCredentials.getJSONObject("credentials");String tmpSecretId = credentials.getString("tmpSecretId");String tmpSecretKey = credentials.getString("tmpSecretKey");String sessionToken = credentials.getString("sessionToken");// Example 2 for obtaining temporary keys: If directly calling the TencentCloud API, or using the TencentCloud API SDK to call the temporary key API, it returns in uppercase camel case format.// long expiredTime = keyAndCredentials.getLong("ExpiredTime");// JSONObject credentials = keyAndCredentials.getJSONObject("Credentials");// String tmpSecretId = credentials.getString("TmpSecretId");// String tmpSecretKey = credentials.getString("TmpSecretKey");// String sessionToken = credentials.getString("Token");// 2. Initialize the COS SDK: CosXmlService and TransferManager// Create a CosXmlServiceConfig object and modify the default configuration parameters as neededCosXmlServiceConfig serviceConfig = new CosXmlServiceConfig.Builder().setRegion(region).isHttps(true) // Enables HTTPS requests, defaults to HTTP requests.builder();// Initialize aCosXmlServiceinstance. You may skip setting the temporary key callbackCosXmlService cosXmlService = new CosXmlService(context, serviceConfig);// Initialize TransferConfig using the default configuration here. If customization is needed, see the SDK API documentation.TransferConfig transferConfig = new TransferConfig.Builder().build();// Initialize TransferManagerTransferManager transferManager = new TransferManager(cosXmlService, transferConfig);// 3. Perform the uploadPutObjectRequest putRequest = new PutObjectRequest(bucket, cosKey, filePath);SessionQCloudCredentials sessionQCloudCredentials = new SessionQCloudCredentials(tmpSecretId, tmpSecretKey,sessionToken, startTime, expiredTime);putRequest.setCredential(sessionQCloudCredentials);COSXMLUploadTask uploadTask = transferManager.upload(putRequest, null);// Set the upload progress callbackuploadTask.setCosXmlProgressListener(new CosXmlProgressListener() {@Overridepublic void onProgress(long complete, long target) {// todo Do something to update progress...}});// Set the return result callbackuploadTask.setCosXmlResultListener(new CosXmlResultListener() {@Overridepublic void onSuccess(CosXmlRequest request, CosXmlResult result) {COSXMLUploadTask.COSXMLUploadTaskResult uploadResult =(COSXMLUploadTask.COSXMLUploadTaskResult) result;}// If you are using the kotlin language to make the call, note that the exception in the callback method is nullable; otherwise, the onFail method will not be triggered// i.e.: clientException is of type CosXmlClientException?, and serviceException is of type CosXmlServiceException?@Overridepublic void onFail(CosXmlRequest request,@Nullable CosXmlClientException clientException,@Nullable CosXmlServiceException serviceException) {if (clientException != null) {clientException.printStackTrace();} else {serviceException.printStackTrace();}}});
Request upload and signature information from the server.
/*** Obtain upload and signature information** @param filename File name* @return Upload and signature information*/private JSONObject getKeyAndCredentials(String filename) {// Obtain upload and signature informationHttpURLConnection getConnection = null;try {// The above-mentioned temporary key service (in the production environment, replace it with the official business url)URL url = new URL("http://127.0.0.1:3000/getKeyAndCredentials?filename=" + filename);getConnection = (HttpURLConnection) url.openConnection();getConnection.setRequestMethod("GET");int responseCode = getConnection.getResponseCode();if (responseCode == HttpURLConnection.HTTP_OK) {BufferedReader reader = new BufferedReader(new InputStreamReader(getConnection.getInputStream()));StringBuilder stringBuilder = new StringBuilder();String line;while ((line = reader.readLine()) != null) {stringBuilder.append(line);}reader.close();JSONObject jsonObject;try {// The server API needs to return: the upload bucket, region, object key with random path, and temporary credentialsjsonObject = new JSONObject(stringBuilder.toString());return jsonObject;} catch (JSONException e) {e.printStackTrace();}} else {Log.e("getKeyAndCredentials", "getKeyAndCredentials HTTP error code: " + responseCode);}} catch (IOException e) {e.printStackTrace();Log.e("getKeyAndCredentials", "getKeyAndCredentials Error sending GET request: " + e.getMessage());} finally {if (getConnection != null) {getConnection.disconnect();}}return null;}