tencent cloud

Upload Objects Practice Tutorial
Last updated:2026-01-13 11:35:59
Upload Objects Practice Tutorial
Last updated: 2026-01-13 11:35:59
This document describes how to set up a secure temporary key service and how to use the JavaScript SDK to initialize and upload.
Note:
Before starting the upload, ensure that you have completed the cross-domain configuration and the SDK initialization.

Solution strengths

Permission security: The permission scope is restricted to a secure range, which can only be used for uploading 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. The server generates a random COS file path with a timestamp based on the file extension, applies for a temporary key with corresponding permissions and a COS key, and returns them to the frontend.
3. The frontend uses the uploadFile advanced upload interface to upload files to COS.

Temporary Key Setup

Temporary keys (temporary access credentials) are keys with limited permissions obtained through the CAM TencentCloud API interface. When a COS API request is initiated, the three fields returned by the temporary key acquisition interface — TmpSecretId, TmpSecretKey, and Token — are used to calculate the signature.
The getKeyAndCredentials interface returns temporary key information, as well as the Bucket, Region, and cosKey required for the upload.
The following shows example code in various languages:
NodeJS
Go
PHP
Python
Java
.Net
The complete code can be referred to in the sample code.
// Temporary key service sample
const STS = require('qcloud-cos-sts');
const express = require('express');
const pathLib = require('path');
// Configure 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,
// Key upload permission list
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 COS file path and name to be uploaded
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();
});
// Obtain temporary key
function getSts({ cosKey, condition }) {
return new Promise((resolve, reject) => {
// Obtain temporary key
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-related 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', // Support setting the sts private network domain
policy: policy,
},
function (err, tempKeys) {
if (tempKeys) tempKeys.startTime = startTime;
if (err) {
reject(err);
} else {
resolve(tempKeys);
}
}
);
});
}
// Return the temporary key and upload information, and the client calculates the signature on its own
app.get('/getKeyAndCredentials', function (req, res, next) {
// User session status validation is implemented by the business side, such as token validation
// const userToken = req.query.userToken;
// const canUpload = checkUserRole(userToken);
// if (!canUpload) {
// res.send({ error: 'The current user has no upload permission' });
// return;
// }

// File upload can control the type and size, enable as needed.
const permission = {
limitExt: false, // Limit the file extension for upload
extWhiteList: ['jpg', 'jpeg', 'png', 'gif', 'bmp'], // Allowed file extensions for upload
limitContentType: false, // Limit the upload contentType
limitContentLength: false, // Limit the file size for upload
};
// The client passes the original file name, and a random Key is generated here 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 the file extensions for upload
if (permission.limitExt) {
const extInvalid = !ext || !extWhiteList.includes(ext);
if (extInvalid) {
res.send({ error: 'Invalid file. Upload is blocked' });
}
}
// 2. Limit the content-type for file upload
if (permission.limitContentType) {
Object.assign(condition, {
'string_like_if_exist': {
// Only allow image content-types for upload
'cos:content-type': 'image/*'
}
});
}

// 3. Limit the file size for upload
if (permission.limitContentLength) {
Object.assign(condition, {
'numeric_less_than_equal': {
// The upload size limit must not exceed 5MB (only applies to 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 referred to 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"), // The user's SecretId. It is recommended to use a sub-account key. Authorization should follow the principle of least privilege to reduce usage risks. For information on how to obtain a sub-account key, see https://www.tencentcloud.com/document/product/598/37140?from_cn_redirect=1
SecretKey: os.Getenv("SECRETKEY"), // The user's SecretKey. It is recommended to use a sub-account key. Authorization should follow the principle of least privilege to reduce usage risks. For information on how to obtain a sub-account key, see 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 primitive types
result[key] = fieldValue.Interface()
}
}

return result
}

// Convert to camelCase format (with the first letter in lowercase)
func toLowerCamel(s string) string {
if s == "" {
return s
}

// Handle all-uppercase words (such as ID)
if strings.ToUpper(s) == s {
return strings.ToLower(s)
}

// Standard camelCase conversion
runes := []rune(s)
runes[0] = unicode.ToLower(runes[0])
return string(runes)
}

func main() {

config := getConfig()

permission := getPermission()

c := sts.NewClient(
// Obtain a secret key through environment variables; the os.Getenv method indicates obtaining environment variables
config.SecretId, //os.Getenv("SECRETID"), // The user's SecretId. It is recommended to use a sub-account key. Authorization should follow the principle of least privilege to reduce usage risks. For information on how to obtain a sub-account key, see https://www.tencentcloud.com/document/product/598/37140?from_cn_redirect=1
config.SecretKey, //os.Getenv("SECRETKEY"), // The user's SecretKey. It is recommended to use a sub-account key. Authorization should follow the principle of least privilege to reduce usage risks. For information on how to obtain a sub-account key, refer to https://www.tencentcloud.com/document/product/598/37140?from_cn_redirect=1
nil,
// sts.Host("sts.internal.tencentcloudapi.com"), // Set the domain. Default domain: sts.tencentcloudapi.com
// sts.Scheme("http"), // Set the protocol. Default is https. Public cloud sts does not allow using http to obtain 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", "Invalid file. Upload is blocked")
return
}
}

if permission.LimitContentType {
condition["string_like_if_exist"] = map[string]interface{}{
// Only image content-types are allowed for upload
"cos:content-type": "image/*",
}
}

// 3. Limit the upload file size
if permission.LimitContentLength {
condition["numeric_less_than_equal"] = map[string]interface{}{
// The upload size limit must not exceed 5MB (only applies to 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{
{
// Permission list for the key. Simple upload and multipart upload require the following permissions. For other permission lists, see https://www.tencentcloud.com/document/product/436/31923?from_cn_redirect=1
Action: config.AllowActions,
Effect: "allow",
Resource: []string{
// Change to the allowed path prefix here. You can determine the specific upload path based on your website's user login status. Examples: a.jpg or a/* or * (Using wildcard * carries significant security risks. Evaluate its use carefully.)
// The bucket naming format is BucketName-APPID. The bucket entered here must be in this format
"qcs::cos:ap-guangzhou:uid/" + config.appId + ":" + config.Bucket + "/" + key,
},
// Start building the effective conditions condition
// For detailed configuration rules of conditions and the types of conditions supported by COS, refer to https://www.tencentcloud.com/document/product/436/71306?from_cn_redirect=1
Condition: condition,
},
},
},
}

// case 1 Request temporary key
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 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 referred to in the sample code.
<?php
require_once __DIR__ . '/vendor/autoload.php';

use QCloud\\COSSTS\\Sts;

// Generate the COS file path and name to be uploaded
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 key for single file upload permission
function getKeyAndCredentials($filename) {
// User session status validation is implemented by the business side, such as token validation
// $canUpload = checkUserRole($userToken);
// if (!$canUpload) {
// return 'The current user has no upload permission';
// }

// File upload can control the type and size, enable as needed.
$permission = array(
'limitExt' => false, // Restrict the file extension for upload
'extWhiteList' => ['jpg', 'jpeg', 'png', 'gif', 'bmp'], // Allowed file extensions for upload
'limitContentType' => false, // Limit the upload contentType
'limitContentLength' => false, // Limit the file size for upload
);
$condition = array();

// The client passes the original file name, and a random Key is generated here based on the file extension.
$ext = pathinfo($filename, PATHINFO_EXTENSION);

// 1. Limit the file extensions for upload
if ($permission['limitExt']) {
if ($ext === '' || array_key_exists($ext, $permission['extWhiteList'])) {
return 'Invalid file. Upload is blocked';
}
}

// 2. Limit the content-type for file upload
if ($permission['limitContentType']) {
// Only allow image content-type for upload
$condition['string_like_if_exist'] = array('cos:content-type' => 'image/*');
}

// 3. Limit the file size for upload
if ($permission['limitContentLength']) {
// The upload size limit cannot 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. For plaintext secrets, enter directly as 'xxx'. Do not place them in the getenv() function
'secretKey' => getenv('GROUP_SECRET_KEY'), // Fixed secret. For plaintext secrets, enter directly as 'xxx'. Do not place them 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 permissions for the path of the current key
// List of permissions for the key. Simple uploads and multipart uploads require the following permissions. For other permissions, see 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 referred to 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",
# Key upload operations permission list
"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 the file extension for upload
"extWhiteList": ["jpg", "jpeg", "png", "gif", "bmp"], # Allowed file extensions for upload
"limitContentType": False, # Limit the upload contentType
"limitContentLength": False, # Limit the file size for upload
}


# Generate the COS file path and name to be uploaded
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 the file extensions for upload
if permission["limitExt"]:
ext_invalid = not ext or ext not in permission["extWhiteList"]
if ext_invalid:
print('Invalid file. Upload is blocked')

# 2. Limit the content-type for file upload
if permission["limitContentType"]:
condition.update({
"string_like_if_exist": {
# Only allow image content-types for upload
"cos:content-type": "image/*"
}
})

# 3. Limit the file size for upload
if permission["limitContentLength"]:
condition.update({
"numeric_less_than_equal": {
# The upload size limit must not exceed 5MB (only applies to simple uploads)
"cos:content-length": 5 * 1024 * 1024
}
})


def get_credential_demo():
credentialOption = {
# Validity period of temporary key, in seconds
'duration_seconds': config.get('durationSeconds'),
'secret_id': config.get("secretId"),
# Permanent 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 referred to 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;
}

// Get 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 limit
Boolean limitExt = false; // Restrict the file extension for upload
List extWhiteList = Arrays.asList("jpg", "jpeg", "png", "gif", "bmp"); // Allowed file extensions for upload
Boolean limitContentType = false; // Limit the upload contentType
Boolean limitContentLength = false; // Limit the file size for upload


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

// 1. Limit the file extensions for upload
if (limitExt) {
boolean extInvalid = ext == null || !extWhiteList.contains(ext);
if (extInvalid) {
System.out.println("Invalid file. Upload is blocked.");
return null;
}
}

// 2. Limit the content-type for file upload
if (limitContentType) {
condition.put("string_like_if_exist", new HashMap<String, String>() {{
put("cos:content-type", "image/*");
}});
}

// 3. Limit the file size for upload (applies to simple upload only)
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;
}

/**
* A basic example of requesting temporary credentials, suitable for uniformly granting a set of operation permissions on a batch of object paths 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 referred to 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 key
string secretId = "";
string secretKey = "";

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

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 operation scope, using upload operation as an example here
"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. Restrict file extensions for upload
if (limitExt)
{
var extInvalid = string.IsNullOrEmpty(ext) || !extWhiteList.Contains(ext);
if (extInvalid)
{
Console.WriteLine("Invalid file. Upload is prohibited.");
return null;
}
}

// 2. Limit the upload file content-type
if (limitContentType)
{
condition["string_like_if_exist"] = new Dictionary<string, string>
{
{ "cos:content-type", "image/*" } // Only allow image content-types for upload
};
}

// 3. Limit the file size for upload (applies to simple upload only)
if (limitContentLength)
{
condition["numeric_less_than_equal"] = new Dictionary<string, long>
{
{ "cos:content-length", 5 * 1024 * 1024 } // The upload size limit must not 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 temporary access credentials for federated identity https://www.tencentcloud.com/document/product/1312/48195?from_cn_redirect=1
public Dictionary<string, object> GetCredential()
{

var config = getConfig();
// Obtain temporary key
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}");
}
}
}

The Client Initiates the Upload

import COS from 'cos-js-sdk-v5';

// console.log(COS.version); The sdk version must be at least 1.8.3

// Upload a file, where 'file' is the selected file
function upload(file) {
// stsUrl is the temporary key service established above
const stsUrl = `http://127.0.0.1:3000/getKeyAndCredentials?filename=${file.name}`;
return new Promise((resolve, reject) => {
fetch(stsUrl)
.then(response => response.json())
.then(data => {
// The server-side interface needs to return: the upload bucket, region, object key with a random path, and temporary key
console.log('getKeyAndCredentials:', data);

// Example 1 for obtaining temporary keys: If obtaining the format of temporary key fields via qcloud-cos-sts-sdk. In the return value, obtain temporary key information and the file path information for upload.
const { credentials = {}, startTime, expiredTime, bucket, region, key } = data;
const { tmpSecretId, tmpSecretKey, sessionToken } = credentials;

// Example 2 for obtaining temporary keys: If directly requesting the TencentCloud API or using the TencentCloud API SDK to call the temporary key interface, the returned format is UpperCamelCase
// const tmpSecretId = data.Credentials.TmpSecretId;
// const tmpSecretKey= data.Credentials.TmpSecretKey;
// const sessionToken = data.Credentials.Token;
// const expiredTime= data.ExpiredTime;

// Validate the returned parameters of getUploadParams, subject to the actual returned format.
const params = { tmpSecretId, tmpSecretKey, sessionToken, bucket, region, key };
const emptyParam = Object.keys(params).find(key => !params[key]);
if (emptyParam) {
reject(`Parameter error: ${emptyParam} cannot be empty`);
return;
}
// Create a JS SDK instance, passing in temporary key parameters
// Other configuration items can be found below: Initialization Configuration Items
const cos = new COS({
SecretId: tmpSecretId,
SecretKey: tmpSecretKey,
SecurityToken: sessionToken,
StartTime: startTime,
ExpiredTime: expiredTime,
});
// Upload documents.
cos.uploadFile({
Bucket: bucket,
Region: region,
Key: key,
Body: file, // The file object to be uploaded.
onProgress: function(progressData) {
console.log('Upload progress:', progressData);
}
}, function (err, data) {
console.log('Upload completed', err || data);
if (err) {
reject(err);
} else {
resolve(data);
}
});
}).catch(error => {
console.error('Failed to obtain the upload path and temporary keys', error);
reject(error);
});
});
}

References

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

Feedback