腾讯云 对象存储SDK接入指南(NodeJS 版本)
首先要在后台创建一个存储桶,这个就不论述了。
本文主要介绍如何在服务端(Nodejs)接入腾讯SDK上传和删除存储桶文件。
通过 npm 安装用于进行对象操作的SDK
npm i cos-nodejs-sdk-v5 --save
这是为了下一步初始化 SDK 用的,需要用到存储桶密钥。
打开 密钥管理后台 新建一个密钥。


记录下SecretId和SecretKey。SecretKey 只有创建的时候才能看见,所以一定要在创建的时候记录下来。
拿到的密钥之后就可以进行初始化了。初始化其实就是身份验证,只有验证身份后通过后才能进行上传删除等操作。
对于初始化SDK,官方提供了两种方式,一种是使用使用永久密钥进行初始化,一种是使用临时密钥进行初始化。
使用永久密钥进行初始化比较简单粗暴,直接传入SecretId和SecretKey,就可以了。
但是由于这种方式进行身份验证是永久生效,并且没有权限约束的,所以密钥一旦泄露,就可以随时随意对你的存储桶进行操作,安全系数比较低。
初始化示例代码如下:
const COS = require('cos-nodejs-sdk-v5')
const cos = new COS({
SecretId: 'your SecretId',
SecretKey: 'your SecretKey',
})
// 上传文件
cos.putObject()
使用临时密钥初始化进行初始化,虽然过程会复杂一点,但是由于密钥是有时效的,并且操作有权限约束,所以相比于永久密钥会更加安全可靠。
在进行临时密钥初始化时,需要传递一个 getAuthorization(options,callback) 方法,getAuthorization 方法在初始化时不会被调用,而是在进行对象操作时才会调用。
getAuthorization 的 callback 参数是一个函数,需要在 getAuthorization 方法最后调用 callback 函数返回临时密钥信息,临时密钥信息包括这些字段:
| 参数 | 类型 | 描述 | 是否必须 |
|---|---|---|---|
| TmpSecretId | String | 临时密钥的 tmpSecretId | 是 |
| TmpSecretKey | String | 临时密钥的 tmpSecretKey | 是 |
| SecurityToken | String | 临时密钥的 sessionToken | 是 |
| StartTime | Number | 临时密钥开始时间戳 | 是 |
| ExpiredTime | Number | 临时密钥失效时间戳 | 是 |
初始化示例代码如下:
const COS = require('cos-nodejs-sdk-v5');
const cos = new COS({
getAuthorization: async function (options, callback) {
// 初始化时不会调用,只有调用 cos 方法(例如 cos.putObject)时才会进入
// 异步获取临时密钥
const data = await getStsToken()
callback({
TmpSecretId: data.tmpSecretId, // 临时密钥的 tmpSecretId
TmpSecretKey: data.tmpSecretKey, // 临时密钥的 tmpSecretKey
SecurityToken: data.sessionToken, // 临时密钥的 sessionToken
StartTime: data.startTime, // 时间戳,单位秒,如:1580000000
ExpiredTime: data.expiredTime, // 临时密钥失效时间戳,是申请临时密钥时,时间戳加durationSeconds
});
}
});
如何生成这些密钥信息呢?
官方提供了这个SDK ,我们需要传递相应的参数来获取密钥信息,例如前面提到的权限和过期时间等
在 STS 云API 后台 ,官方提供了不同语言的SDK以及示例,这里我们选择NodeJS版本。

先安装STS SDK,这是Nodejs版本用于生成临时密钥信息的SDK
npm i tencentcloud-sdk-nodejs-sts --save
安装完SDK后,我们要使用这个SDK获取临时密钥信息,需要提供以下参数:
| 参数 | 类型 | 是否必填 | 参考值 | 描述 |
|---|---|---|---|---|
| SecretId | String | 是 | 前面获取的 SecretId | |
| SecretKey | String | 是 | 前面获取的 SecretKey | |
| Name | String | 是 | test | 自定义调用方的英文名称 随便写什么都可以 |
| region | String | 是 | ap-beijing | 存储位置 |
| Policy | String | 是 | {"version": "2.0","statement": [{"effect": "allow","action": ["name/cos:PutObject","name/cos:DeleteObject"],"resource": "*"}]} | |
| - version | 是 | 2.0 | 描述策略语法版本 | |
| - statement | - | - | - | - |
| -- effect | 是 | allow | 描述声明产生的结果 | |
| -- action | 是 | ["name/cos:PutObject","name/cos:DeleteObject"] | 描述允许的操作 action 为"name/cos:PutObject"(上传对象)、"name/cos:DeleteObject"(删除对象),更多接口请参见 支持 CAM 的对象存储业务接口。 | |
| -- resource | 是 | * | 描述授权的具体数据 resource,授予操作 action 的所有资源的操作权限 | |
| DurationSeconds | Number | 否 | 3600 | 指定临时证书的有效期 3600秒,不指定默认为1800秒。 |
获取临时密钥信息示例代码:
import tencentcloud from "tencentcloud-sdk-nodejs-sts";
async function getStsToken(){
try {
// 我使用的是Nuxt,这里是拿到环境变量中的SecretId和SecretKey
const {tSecretId,tSecretKey} = useRuntimeConfig()
const StsClient = tencentcloud.sts.v20180813.Client;
const clientConfig = {
credential: {
secretId: tSecretId,
secretKey: tSecretKey,
},
// 填写创建存储桶时设置的存储位置 例:华北地区(北京)ap-beijing
region: "ap-singapore",
profile: {
httpProfile: {
endpoint: "sts.tencentcloudapi.com",
},
},
};
const client = new StsClient(clientConfig);
const params = {
// 自定义调用方的英文名称 随便写什么都可以
Name:'puyuanhao',
// JSON 字符串
Policy:'{"version":"2.0","statement":[{"effect":"allow","action":["name/cos:PutObject","name/cos:DeleteObject"],"resource":"*"}]}'
}
const data = await client.GetFederationToken(params)
return data
} catch (error) {
console.log(error.message)
}
}
返回的 data 中就包含我们需要的密钥信息,结构如下:
{
"Credentials": {
"TmpSecretId": "response TmpSecretId",
"TmpSecretKey": "response TmpSecretKey",
"Token": "response Token"
},
"ExpiredTime": 3600,
}
用于初始化临时密钥的信息基本都在这了,这里并没有返回 StartTime 这个字段,我们可以通过 Date 对象自行生成
// 腾讯云COS上传
import tencentcloud from "tencentcloud-sdk-nodejs-sts";
import COS from 'cos-nodejs-sdk-v5'
// 获取腾讯临时密钥
async function requestToken(){
try {
const {tSecretId,tSecretKey} = useRuntimeConfig()
const StsClient = tencentcloud.sts.v20180813.Client;
const clientConfig = {
credential: {
secretId: tSecretId,
secretKey: tSecretKey,
},
region: "ap-singapore",
profile: {
httpProfile: {
endpoint: "sts.tencentcloudapi.com",
},
},
};
// 实例化要请求产品的client对象,clientProfile是可选的
const client = new StsClient(clientConfig);
const params = {
Name:'puyuanhao',
Policy:'{"version":"2.0","statement":[{"effect":"allow","action":["name/cos:PutObject","name/cos:DeleteObject"],"resource":"*"}]}'
}
const data = await client.GetFederationToken(params)
return data
} catch (error) {
console.log(error.message)
}
}
const cos = new COS({
getAuthorization:async function(options,callback){
const StartTime = +(Date.now().toString().slice(0,-3))
const data = await requestToken()
if(!data){
throw new Error('get tencent cos token error')
}
callback({
TmpSecretId: data.Credentials.TmpSecretId,
TmpSecretKey: data.Credentials.TmpSecretKey,
SecurityToken: data.Credentials.Token,
ExpiredTime: data.ExpiredTime,
StartTime,
})
}
});
初始化后就可以通过 cos 对象进行对象操作了。
cos 对象有很多对象方法,这里只列举常用的上传、删除操作,完整的对象操作文档请参考 对象操作文档
使用putObject(options,callback)方法上传文件
options参数如下:(这里列出了几个必需的参数)
| 参数 | 类型 | 描述 | 是否必填 |
|---|---|---|---|
| Bucket | String | 存储桶的名称,命名格式为 BucketName-APPID,此处填写的存储桶名称必须为此格式 | 是 |
| Region | String | 存储桶所在地域 | 是 |
| Key | String | 对象键,上传路径,例如 folder/object.jpg | 是 |
| Body | Stream | 上传的文件流 | 是 |
| StorageClass | String | 对象的存储类型,枚举值:STANDARD、STANDARD_IA、ARCHIVE、DEEP_ARCHIVE 等,更多存储类型请参见 [存储类型概述] 不同类型的存储方式价格不一样,建议仔细看一下 | 否 |
callback 说明如下:
| 参数 | 类型 | 描述 |
|---|---|---|
| err | Object | 请求发生错误时返回的对象,包括网络错误和业务错误。如果请求成功则为空 |
| data | Object | 请求成功时返回的对象,如果请求发生错误,则为空 |
上传文件示例:
cos.putObject({
Bucket: 'gear-bucket-1318693309', /* 必须 */
Region: 'ap-singapore', /* 必须 */
Key: 'folder/object.jpg', /* 必须 */
StorageClass: 'MAZ_STANDARD',
Body: fileStream, // 上传文件对象
}, function(err, data) {
if(err){
console.log(err)
}else{
console.log(data)
}
});
使用deleteObject(options,callback)方法删除文件
options参数和上传文件参数基本一致,示例代码如下:
cos.deleteObject({
Bucket: 'gear-bucket-1318693309', /* 必须 */
Region: 'ap-singapore', /* 必须 */
Key: key, /* 必须 */
}, function(err, data) {
if(err){
reject(err)
}else{
resolve(data)
}
});
已将 上传、删除、批量删除抽离到 tencent_upload.js 中,完整代码如下
import tencentcloud from "tencentcloud-sdk-nodejs-sts";
import COS from 'cos-nodejs-sdk-v5'
import { Readable } from 'node:stream'
// 获取腾讯临时密钥
async function getStsToken(){
try {
const {tSecretId,tSecretKey} = useRuntimeConfig()
const StsClient = tencentcloud.sts.v20180813.Client;
const clientConfig = {
credential: {
secretId: tSecretId,
secretKey: tSecretKey,
},
region: "ap-singapore",
profile: {
httpProfile: {
endpoint: "sts.tencentcloudapi.com",
},
},
};
// 实例化要请求产品的client对象,clientProfile是可选的
const client = new StsClient(clientConfig);
const params = {
Name:'puyuanhao',
Policy:'{"version":"2.0","statement":[{"effect":"allow","action":["name/cos:PutObject","name/cos:DeleteObject"],"resource":"*"}]}'
}
const data = await client.GetFederationToken(params)
return data
} catch (error) {
console.log(error.message)
}
}
const cos = new COS({
getAuthorization:async function(options,callback){
const StartTime = +(Date.now().toString().slice(0,-3))
const data = await getStsToken()
if(!data){
throw new Error('get tencent cos token error')
}
callback({
TmpSecretId: data.Credentials.TmpSecretId,
TmpSecretKey: data.Credentials.TmpSecretKey,
SecurityToken: data.Credentials.Token,
ExpiredTime: data.ExpiredTime,
StartTime,
})
}
});
// 上传文件
export function uploadFile(file,path='',progress){
const name = (new Date()).toLocaleString().replace(/\//g,'-').replace(/\s/g,'_')
const suffix = file.name.split('.').pop()
const key = `${path}/${name}.${suffix}`
const readStream = file.stream()
const nodeStream = Readable.fromWeb(readStream)
return new Promise((resolve,reject) => {
cos.putObject({
Bucket: 'gear-bucket-1318693309', /* 必须 */
Region: 'ap-singapore', /* 必须 */
Key: key, /* 必须 */
StorageClass: 'MAZ_STANDARD',
Body: nodeStream, // 上传文件对象
onProgress: function(progressData) {
progress && progress(progressData)
}
}, function(err, data) {
if(err){
reject(err)
}else{
resolve({
key
})
}
});
})
}
// 删除文件
export function deleteFile(key){
return new Promise((resolve,reject) => {
cos.deleteObject({
Bucket: 'gear-bucket-1318693309', /* 必须 */
Region: 'ap-singapore', /* 必须 */
Key: key, /* 必须 */
}, function(err, data) {
if(err){
reject(err)
}else{
resolve(data)
}
});
})
}
// 批量删除文件
export function deleteFiles(keys){
return new Promise((resolve,reject) => {
cos.deleteMultipleObject({
Bucket: 'gear-bucket-1318693309', /* 必须 */
Region: 'ap-singapore', /* 必须 */
Objects: keys.map(key => ({Key:key})),
}, function(err, data) {
if(err){
reject(err)
}else{
resolve(data)
}
});
})
}