tencent cloud

Upload Object Hands-on Tutorial
Last updated:2026-02-27 15:05:10
Upload Object Hands-on Tutorial
Last updated: 2026-02-27 15:05:10
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:
NodeJS
Go
PHP
Python
Java
.Net
The complete code can be found in the sample code.
// Temporary key service example
const STS = require('qcloud-cos-sts');
const express = require('express');
const pathLib = require('path');
// Configuration parameters
const 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 operations
allowActions: [
// 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 upload
const 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 service
const 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 keys
function getSts({ cosKey, condition }) {
return new Promise((resolve, reject) => {
// Obtain temporary keys
const 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 path
resource,
// 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 sts
policy: 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 signature
app.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 needed
const permission = {
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
};
// The client passes the original filename, and a random Key is generated based on the file extension
const 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 extensions
if (permission.limitExt) {
const extInvalid = !ext || !extWhiteList.includes(ext);
if (extInvalid) {
res.send({ error: 'Illegal file, upload prohibited' });
}
}
// 2. Limit uploaded file content-type
if (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 size
if (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 service
app.listen(3000);
console.log('app is listening at http://127.0.0.1:3000');
The complete code can be found in the sample code.
package main

import (
"fmt"
"github.com/tencentyun/qcloud-cos-sts-sdk/go"
"math/rand"
"os"
"time"
)

type Config struct {
filename string
appId string
SecretId string
SecretKey string
Proxy string
DurationSeconds int
Bucket string
Region string
AllowActions []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()) + 1
ymd := 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://www.tencentcloud.com/document/product/598/37140?from_cn_redirect=1
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://www.tencentcloud.com/document/product/598/37140?from_cn_redirect=1
Proxy: 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 camelCase
key := toLowerCamel(field.Name)

// Handle nested structs
if fieldValue.Kind() == reflect.Struct ||
(fieldValue.Kind() == reflect.Ptr && fieldValue.Elem().Kind() == reflect.Struct) {

if fieldValue.IsNil() && fieldValue.Kind() == reflect.Ptr {
result[key] = nil
continue
}

result[key] = StructToCamelMap(fieldValue.Interface())
} else {
// Handle basic types
result[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 conversion
runes := []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://www.tencentcloud.com/document/product/598/37140?from_cn_redirect=1
config.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://www.tencentcloud.com/document/product/598/37140?from_cn_redirect=1
nil,
// 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 size
if 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://www.tencentcloud.com/document/product/436/18023?from_cn_redirect=1
opt := &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://www.tencentcloud.com/document/product/436/31923?from_cn_redirect=1
Action: 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://www.tencentcloud.com/document/product/436/71306?from_cn_redirect=1
Condition: condition,
},
},
},
}

// case 1 Request temporary keys
res, err := c.GetCredential(opt)
if err != nil {
panic(err)
}
// Convert to camelCase map
resultMap := StructToCamelMap(res)
resultMap["bucket"] = config.Bucket
resultMap["region"] = config.Region
resultMap["key"] = key
// Print the result
jsonBytes, err := json.MarshalIndent(resultMap, "", " ")
if err != nil {
panic(err)
}
// Convert to string and print
fmt.Println(string(jsonBytes))
}
The complete code can be found in the sample code.
<?php
require_once __DIR__ . '/vendor/autoload.php';

use QCloud\\COSSTS\\Sts;

// Generate the file path and name for the COS upload
function 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 authorization
function 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 extensions
if ($permission['limitExt']) {
if ($ext === '' || array_key_exists($ext, $permission['extWhiteList'])) {
return 'Illegal file, upload prohibited';
}
}

// 2. Limit uploaded file content-type
if ($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 size
if ($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://www.tencentcloud.com/document/product/436/31923?from_cn_redirect=1
'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;
}
The complete code can be found in the sample code.
#!/usr/bin/env python
# coding=utf-8
import json
import os
import datetime
import random

from sts.sts import Sts

if __name__ == '__main__':

# Configuration Parameters
config = {
"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 COS
def 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_key


segments = 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 extensions
if 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-type
if permission["limitContentType"]:
condition.update({
"string_like_if_exist": {
# Only allow uploading files with image content-type
"cos:content-type": "image/*"
}
})

# 3. Limit uploaded file size
if 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()
The complete code can be found in the sample code.
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 information
public 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 limitations
Boolean limitExt = false; // Limit uploaded file extensions
List extWhiteList = Arrays.asList("jpg", "jpeg", "png", "gif", "bmp"); // Allowed file extensions
Boolean limitContentType = false; // Restrict upload content type
Boolean limitContentLength = false; // Limit uploaded file size


Map<String, Object> condition = new HashMap();

// 1. Limit uploaded file extensions
if (limitExt) {
boolean extInvalid = ext == null || !extWhiteList.contains(ext);
if (extInvalid) {
System.out.println("Illegal file, upload prohibited");
return null;
}
}

// 2. Limit uploaded file content-type
if (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 policy
Map<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 config
TreeMap <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
*/
@Test
public 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 !");
}
}
}
The complete code can be found in the sample code.
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 key
string secretId = "";
string secretKey = "";

string bucket = "bucket-125000000";
string appId = "125000000";
string region = "ap-guangzhou";
string filename = "test.jpg";
int time = 1800;
// Limit
Boolean limitExt = false; // Limit uploaded file extensions
List<string> extWhiteList = new List<String> { "jpg", "jpeg", "png", "gif", "bmp" }; // Allowed file extensions
Boolean limitContentType = false; // Restrict upload content type
Boolean limitContentLength = false; // Limit uploaded file size

public 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 zeros
string 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 extensions
if (limitExt)
{
var extInvalid = string.IsNullOrEmpty(ext) || !extWhiteList.Contains(ext);
if (extInvalid)
{
Console.WriteLine("Illegal file, upload prohibited");
return null;
}
}

// 2. Limit uploaded file content-type
if (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 output
string 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://www.tencentcloud.com/document/product/1312/48195?from_cn_redirect=1
public Dictionary<string, object> GetCredential()
{

var config = getConfig();
// Obtain temporary keys
Dictionary<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 filePath
String filePath = "/path/to/your/file.txt";

// 1. Request upload and signature information from the server
File file = new File(filePath);
// The getKeyAndCredentials method is in the next code block
JSONObject 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 response
long 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 needed
CosXmlServiceConfig serviceConfig = new CosXmlServiceConfig.Builder()
.setRegion(region)
.isHttps(true) // Enables HTTPS requests, defaults to HTTP requests
.builder();
// Initialize a CosXmlService instance. You may skip setting the temporary key callback
CosXmlService 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 TransferManager
TransferManager transferManager = new TransferManager(cosXmlService, transferConfig);

// 3. Perform the upload
PutObjectRequest 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 callback
uploadTask.setCosXmlProgressListener(new CosXmlProgressListener() {
@Override
public void onProgress(long complete, long target) {
// todo Do something to update progress...
}
});
// Set the return result callback
uploadTask.setCosXmlResultListener(new CosXmlResultListener() {
@Override
public 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?
@Override
public 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 information
HttpURLConnection 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 credentials
jsonObject = 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;
}

References

Was this page helpful?
You can also Contact Sales or Submit a Ticket for help.
Yes
No

Feedback