tencent cloud

Upload Objects Practice Tutorial
Last updated:2026-01-26 14:53:10
Upload Objects Practice Tutorial
Last updated: 2026-01-26 14:53:10
This document describes how to set up a secure temporary key service and how to use the WeChat Mini Program SDK to initialize and upload.
Note:
Before starting the upload, ensure that you have completed the Mini Program allowlist configuration and finished the SDK initialization.

Solution strengths

Permission security: It can effectively restrict the permission scope to only allow uploading 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 a file. The client sends the original filename to the server.
2. The server generates a random COS file path with a timestamp based on the file name suffix, applies for a temporary key with corresponding permissions and the cos key, and returns them to the frontend.
3. The frontend uses the uploadFile advanced upload API to upload files to COS.

Temporary Key Establishment

Temporary key (Temporary access credentials) is a permission-restricted key obtained through the CAM TencentCloud API interface. When a COS API request is initiated, the three fields—TmpSecretId, TmpSecretKey, and Token—from the temporary key obtaining interface's returned information are used to calculate the signature.
The getKeyAndCredentials interface returns temporary key information along with the Bucket, Region, and cosKey required for upload.
The following sample code in various languages:
NodeJS
Go
PHP
Python
Java
.Net
Complete code can refer to sample code.
// Temporary key service example
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,
// List of upload operation permissions for keys
allowActions: [
// Simple upload
'name/cos:PutObject',
// Multipart upload
'name/cos:InitiateMultipartUpload',
'name/cos:ListMultipartUploads',
'name/cos:ListParts',
'name/cos:UploadPart',
'name/cos:CompleteMultipartUpload',
],
};

// Generating 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 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 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 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', // supports setting the sts private network domain
policy: policy,
},
function (err, tempKeys) {
if (tempKeys) tempKeys.startTime = startTime;
if (err) {
reject(err);
} else {
resolve(tempKeys);
}
}
);
});
}
// Returns temporary keys and upload information; the client calculates the signature on its own.
app.get('/getKeyAndCredentials', function (req, res, next) {
// The business implements user login status verification independently, such as token verification.
// const userToken = req.query.userToken;
// const canUpload = checkUserRole(userToken);
// if (!canUpload) {
// res.send({ error: 'The current user does not have upload permission' });
// return;
// }

// Upload files can control the type and size, enable as needed
const permission = {
limitExt: false, // Limit file extensions for upload
extWhiteList: ['jpg', 'jpeg', 'png', 'gif', 'bmp'], // allowed file extensions
limitContentType: false, // limit upload contentType
limitContentLength: false, // limit upload file size
};
// The client passes the original file name; a random Key is generated here based on the file extension.
const filename = req.query.filename;
if (!filename) {
res.send({ error: 'Please pass the file name' });
}
const ext = pathLib.extname(filename);
const cosKey = generateCosKey(ext);
const condition = {};
// 1. Limit file extensions for upload
if (permission.limitExt) {
const extInvalid = !ext || !extWhiteList.includes(ext);
if (extInvalid) {
res.send({ error: 'Unauthorized file, upload is not allowed' });
}
}
// 2. Limit upload file content-type
if (permission.limitContentType) {
Object.assign(condition, {
'string_like_if_exist': {
// Only allow image content-types for upload
'cos:content-type': 'image/*'
}
});
}

// 3. Limit upload file size
if (permission.limitContentLength) {
Object.assign(condition, {
'numeric_less_than_equal': {
// Upload size limit cannot 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');
Complete code can refer to 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 sub-account keys and follow the principle of least privilege for authorization 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 sub-account keys and follow the principle of least privilege for authorization 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 primitive types
result[key] = fieldValue.Interface()
}
}

return result
}

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

// Handle all-uppercase words (e.g., 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 the key through environment variables; the os.Getenv method represents obtaining environment variables
config.SecretId, //os.Getenv("SECRETID"), // User's SecretId. It is recommended to use sub-account keys and follow the principle of least privilege for authorization 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 sub-account keys and follow the principle of least privilege for authorization 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, default domain sts.tencentcloudapi.com
// sts.Scheme("http"), // Set the protocol, default is https. Public cloud sts does not allow obtaining temporary keys via http; set http only in specific 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", "Unauthorized file, upload is not allowed")
return
}
}

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

// 3. Limit upload file size
if permission.LimitContentLength {
condition["numeric_less_than_equal"] = map[string]interface{}{
// The upload size limit cannot 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{
{
// List of key permissions. Simple upload and multipart upload require the following permissions. For other permissions, refer to https://www.tencentcloud.com/document/product/436/31923?from_cn_redirect=1
Action: config.AllowActions,
Effect: "allow",
Resource: []string{
// Set the allowed path prefix here. You can determine the specific upload path based on the user's login status of your website. Examples: a.jpg, a/*, or * (Using wildcard * poses significant security risks; evaluate its usage 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 condition
// For detailed configuration rules of condition and condition types supported by COS, refer to 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 result
jsonBytes, err := json.MarshalIndent(resultMap, "", " ")
if err != nil {
panic(err)
}
// Convert to string and print
fmt.Println(string(jsonBytes))
}
Complete code can refer to sample code.
<?php
require_once __DIR__ . '/vendor/autoload.php';

use QCloud\\COSSTS\\Sts;

// Generating 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 keys for single-file upload permission
function getKeyAndCredentials($filename) {
// The business implements user login status verification independently, such as token verification.
// $canUpload = checkUserRole($userToken);
// if (!$canUpload) {
// return 'The current user does not have upload permission';
// }

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

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

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

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

// 3. Limit upload file size
if ($permission['limitContentLength']) {
// The upload size limit must not exceed 5MB (applies only to simple upload)
$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 of your bucket
$config = array(
'url' => 'https://sts.tencentcloudapi.com/', // The url should match the domain
'domain' => 'sts.tencentcloudapi.com', // Domain (optional, defaults to sts.tencentcloudapi.com)
'proxy' => '',
'secretId' => getenv('GROUP_SECRET_ID'), // Permanent credentials. For plaintext credentials, enter directly as 'xxx'; must not be placed within getenv() function
'secretKey' => getenv('GROUP_SECRET_KEY'), // Permanent credentials. For plaintext credentials, enter directly as 'xxx'; must not be placed within getenv() function
'bucket' => $bucket, // Replace with your bucket
'region' => $region, // Replace with the region of your bucket
'durationSeconds' => 1800, // Validity period of the credentials
'allowPrefix' => array($cosKey), // Only grant path permission for the current key
// List of permissions granted to the temporary credentials. Simple uploads and multipart uploads require the following permissions. 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;
}
Complete code can refer to 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",
# List of upload operation permissions for keys
"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 file extensions for upload
"extWhiteList": ["jpg", "jpeg", "png", "gif", "bmp"], # allowed file extensions
"limitContentType": False, # Limit upload contentType
"limitContentLength": False, # Limit upload file size
}


# Generating 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 file extensions for upload
if permission["limitExt"]:
ext_invalid = not ext or ext not in permission["extWhiteList"]
if ext_invalid:
print('Unauthorized file, upload is not allowed')

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

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


def get_credential_demo():
credentialOption = {
# Temporary key validity period 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 bucket region
'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()
Complete code can refer to 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 restrictions
Boolean limitExt = false; // Limit file extensions for upload
List extWhiteList = Arrays.asList("jpg", "jpeg", "png", "gif", "bmp"); // allowed file extensions
Boolean limitContentType = false; // Limit upload contentType
Boolean limitContentLength = false; // limit upload file size


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

// 1. Limit file extensions for upload
if (limitExt) {
boolean extInvalid = ext == null || !extWhiteList.contains(ext);
if (extInvalid) {
System.out.println("Unauthorized file, upload is not allowed");
return null;
}
}

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

// 3. Limit upload 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, suitable for granting a set of permissions to a group 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 !");
}
}
}
Complete code can refer to 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;
// Limit
Boolean limitExt = false; // Limit file extensions for upload
List<string> extWhiteList = new List<String> { "jpg", "jpeg", "png", "gif", "bmp" }; // allowed file extensions
Boolean limitContentType = false; // Limit upload contentType
Boolean limitContentLength = false; // limit upload 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, using upload 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 file extensions for upload
if (limitExt)
{
var extInvalid = string.IsNullOrEmpty(ext) || !extWhiteList.Contains(ext);
if (extInvalid)
{
Console.WriteLine("Unauthorized file, upload is not allowed");
return null;
}
}

// 2. Limit file upload 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 upload file size (applies only to simple uploads)
if (limitContentLength)
{
condition["numeric_less_than_equal"] = new Dictionary<string, long>
{
{ "cos:content-length", 5 * 1024 * 1024 } // 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 temporary access credentials for federated identities 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

const COS = require('./lib/cos-wx-sdk-v5.js'); // For development use
// const COS = require('./lib/cos-wx-sdk-v5.min.js'); // Use the minified version for production

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

wx.chooseMedia({
count: 9,
mediaType: ['image','video'],
sourceType: ['album', 'camera'],
maxDuration: 30,
camera: 'back',
success(res) {
uploadFile(res.tempFiles[0]);
}
});

function uploadFile(file) {
const getUploadParams = function() {
return new Promise((resolve, reject) => {
const stsUrl = `http://127.0.0.1:3000/getKeyAndCredentials?filename=${file.tempFilePath}`;
wx.request({
url: stsUrl,
dataType: 'json',
success: function (result) {
resolve(result.data);
},
fail: function() {
reject('get sts error');
}
});
});
}
const upload = async function () {
try {
const data = await getUploadParams();
// The server-side interface needs to return: the upload bucket, region, object key with a random path, and temporary credentials
console.log('getKeyAndCredentials:', data);

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

// Example 2: Obtaining temporary keys - If directly requesting the TencentCloud API or using the TencentCloud API SDK to call the temporary key interface, the response is in UpperCamelCase format
// const tmpSecretId = data.Credentials.TmpSecretId;
// const tmpSecretKey= data.Credentials.TmpSecretKey;
// const sessionToken = data.Credentials.Token;
// const expiredTime= data.ExpiredTime;
// Validate the parameters returned by getUploadParams; the actual returned format prevails
const params = { tmpSecretId, tmpSecretKey, sessionToken, bucket, region, key };
const emptyParam = Object.keys(params).find(key => !params[key]);
if (emptyParam) {
console.error(`Parameter error: ${emptyParam} cannot be empty`);
return;
}
// Create an SDK instance and pass the temporary key parameters
const cos = new COS({
SecretId: tmpSecretId,
SecretKey: tmpSecretKey,
SecurityToken: sessionToken,
StartTime: startTime,
ExpiredTime: expiredTime,
SimpleUploadMethod: 'putObject',
});
cos.uploadFile(
{
Bucket: bucket,
Region: region,
Key: key,
FilePath: file.tempFilePath,
FileSize: file.size,
SliceSize: 1024 * 1024 * 5, // Files larger than 5mb will automatically use multipart upload
},
function (err, data) {
if (err) {
console.error('Upload failed', err);
} else {
console.log('Upload succeeded', data);
}
}
);
} catch (e) {
console.error(e);
}
};
upload();
}

References


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

Feedback