uploadToCOS
上传文件夹到腾讯云 COS(对象存储)。
前置依赖
依赖参数
| 参数名 | 类型 | 说明 |
|---|---|---|
deps.COS | COSConstructor | COS SDK 构造函数 |
deps.existsSync | FileSystem['existsSync'] | 检查文件是否存在 |
deps.statSync | FileSystem['statSync'] | 获取文件状态 |
deps.readdirSync | FileSystem['readdirSync'] | 读取目录内容 |
deps.readFileSync | FileSystem['readFileSync'] | 读取文件内容 |
deps.readFile | FileSystem['readFile'] | 异步读取文件(可选,提供后可提高并发性能) |
deps.join | Path['join'] | 路径拼接 |
deps.basename | Path['basename'] | 获取路径基础名 |
deps.relative | Path['relative'] | 获取相对路径 |
deps.normalize | Path['normalize'] | 标准化路径 |
deps.log | Console['log'] | 日志输出函数 |
deps.error | Console['error'] | 错误日志函数 |
deps.getSecret | (type: SecretType) => TencentCloudSecret | null | 获取密钥函数 |
环境要求
- cos-nodejs-sdk-v5: 腾讯云 COS Node.js SDK
bash
npm install cos-nodejs-sdk-v5函数签名
typescript
function uploadToCOS(
options: UploadToCOSOptions,
deps: UploadToCOSDeps
): Promise<UploadToCOSResult>
interface UploadToCOSOptions {
/** 本地文件夹路径 */
localPath: string
/** COS 存储桶名称 */
bucket: string
/** COS 地域 */
region: string
/** 云端路径前缀 */
cloudPath?: string
/** 密钥类型 */
secretType: SecretType
/** 是否包含根文件夹 */
includeRootFolder?: boolean
/** 是否显示进度 */
showProgress?: boolean
/** 并发上传数量,默认 10 */
concurrency?: number
}
interface UploadToCOSResult {
success: boolean
message?: string
error?: string
filesCount?: number
failedFiles?: string[]
}参数
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
options.localPath | string | 是 | 本地文件夹路径 |
options.bucket | string | 是 | COS 存储桶名称 |
options.region | string | 是 | COS 地域(如 ap-guangzhou) |
options.cloudPath | string | 否 | 云端路径前缀,默认为空 |
options.secretType | SecretType | 是 | 密钥类型(personal/individual/enterprise) |
options.includeRootFolder | boolean | 否 | 是否包含根文件夹名称,默认 false |
options.showProgress | boolean | 否 | 是否显示上传进度,默认 true |
options.concurrency | number | 否 | 并发上传数量,默认 10 |
返回值
| 类型 | 说明 |
|---|---|
Promise<UploadToCOSResult> | 上传结果对象 |
UploadToCOSResult 字段:
| 字段 | 类型 | 说明 |
|---|---|---|
success | boolean | 是否成功 |
message | string? | 成功消息 |
error | string? | 错误消息 |
filesCount | number? | 成功上传的文件数量 |
failedFiles | string[]? | 失败的文件列表 |
工作原理
- 验证本地路径是否存在且为文件夹
- 通过
getSecret获取腾讯云密钥 - 初始化 COS SDK
- 递归遍历文件夹获取所有文件
- 根据
includeRootFolder选项计算云端路径 - 并发上传文件到 COS(默认并发数为 10)
- 返回上传结果和失败文件列表
includeRootFolder 选项说明:
false(默认):不包含根文件夹名称,直接上传文件夹内容- 本地:
./dist/index.html - COS:
/web/index.html
- 本地:
true:保留根文件夹名称作为路径的一部分- 本地:
./dist/index.html - COS:
/web/dist/index.html
- 本地:
示例
基本用法
typescript
import { uploadToCOS } from 'zcw-shared/functions/tencent-cloud/upload.cos'
import type { SecretType, TencentCloudSecret } from 'zcw-shared/types/tencent-cloud'
import COS from 'cos-nodejs-sdk-v5'
import fs from 'fs'
import path from 'path'
// 自定义密钥获取函数
// 注意:实际使用时应该从环境变量或安全的密钥管理服务获取
function getSecret(type: SecretType): TencentCloudSecret | null {
// 根据类型返回对应的密钥
// 这里应该从环境变量或密钥管理服务获取,而不是硬编码
if (type === 'personal') {
return {
secretId: process.env.TENCENT_SECRET_ID || '',
secretKey: process.env.TENCENT_SECRET_KEY || ''
}
}
return null
}
const result = await uploadToCOS(
{
localPath: './dist',
bucket: 'my-bucket-1234567890',
region: 'ap-guangzhou',
cloudPath: '/web',
secretType: 'personal',
includeRootFolder: false,
showProgress: true
},
{
COS,
existsSync: fs.existsSync,
statSync: fs.statSync,
readdirSync: fs.readdirSync,
readFileSync: fs.readFileSync,
readFile: fs.readFile, // 可选,提供后可提高并发性能
join: path.join,
basename: path.basename,
relative: path.relative,
normalize: path.normalize,
log: console.log,
error: console.error,
getSecret
}
)
if (result.success) {
console.log(`上传成功,共 ${result.filesCount} 个文件`)
} else {
console.error(`上传失败: ${result.error}`)
}部署前端项目
typescript
async function deployFrontend() {
const result = await uploadToCOS(
{
localPath: './dist',
bucket: 'my-website-1234567890',
region: 'ap-guangzhou',
cloudPath: '/',
secretType: 'personal',
includeRootFolder: false, // 直接上传 dist 内容到根目录
showProgress: true
},
{
COS,
existsSync: fs.existsSync,
statSync: fs.statSync,
readdirSync: fs.readdirSync,
readFileSync: fs.readFileSync,
readFile: fs.readFile, // 可选,提供后可提高并发性能
join: path.join,
basename: path.basename,
relative: path.relative,
normalize: path.normalize,
log: console.log,
error: console.error,
getSecret: (type) => {
// 自定义密钥获取逻辑
return {
secretId: process.env.TENCENT_SECRET_ID || '',
secretKey: process.env.TENCENT_SECRET_KEY || ''
}
}
}
)
return result
}常见错误
本地路径不存在
typescript
{ success: false, error: '本地路径不存在: ./dist' }路径不是文件夹
typescript
{ success: false, error: '路径不是文件夹: ./file.txt' }无效的密钥类型
typescript
{ success: false, error: '无效的密钥类型: invalid' }文件夹为空
typescript
{ success: false, error: '文件夹为空,没有文件可上传' }注意事项
- 如果 COS 中已存在同名文件,会被覆盖
- 不会上传空文件夹(COS 不支持空文件夹)
- 路径分隔符会自动标准化为
/ - 确保密钥有上传文件到指定存储桶的权限
- 对于大量文件,可以通过增加
concurrency参数加快上传速度 - 并发数设置建议:10-50,过大可能导致服务器拒绝连接或网络拥塞
优化上传速度
typescript
// 方法1:增加并发数 + 使用异步读取
const result = await uploadToCOS(
{
localPath: './dist',
bucket: 'my-bucket-1234567890',
region: 'ap-guangzhou',
cloudPath: '/',
secretType: 'personal',
concurrency: 30, // 设置并发数为 30
showProgress: true
},
{
COS,
existsSync: fs.existsSync,
statSync: fs.statSync,
readdirSync: fs.readdirSync,
readFileSync: fs.readFileSync,
readFile: fs.readFile, // 提供异步读取以进一步提高性能
// ... 其他依赖
}
)性能优化要点:
- 提供
readFile异步读取函数可显著提高并发性能 - 并发数建议根据网络环境和服务器承受能力调整(10-50)
- 对于大量小文件,可以适当提高并发数