coscmd
v1.0.8
Published
一个上传本地文件到腾讯云对象存储(COS)的命令行工具
Downloads
15
Readme
coscmd
一个上传本地文件到腾讯云对象存储(COS)的命令行工具
使用场景
- 希望通过一行简单的命令上传本地文件(夹)到 COS
- 希望前端项目打包完成后自动把产物上传到 COS(参考下面的最佳实践部分)
- 希望文件上传完成后自动预热或刷新 CDN 缓存(需使用腾讯云 CDN 并和 COS 绑定)
- 一次上传到多个 COS 存储桶
环境要求
Node.js v12 及以上版本。
安装
npm i -g coscmd
# 或
yarn global add coscmd
安装太慢?试试 URM
安装完成后,会获得可全局执行的 coscmd
和 cos
(简写)命令。
快速入手
执行
cos upload
命令前,你需要至少在腾讯云创建了一个 COS 存储桶,并把相关的配置添加到了coscmd
的配置文件中。
# 查看 coscmd 中配置的 COS 客户端
cos client list
# 上传本地 index.js 文件到 COS 的 file/index.js 位置
cos upload index.js file/index.js
# 上传本地 dist 文件夹下的全部文件到 COS 的 project/foo 路径下(up 是 upload 的别名)
cos up dist project/foo
# 上传本地 dist 文件夹下的全部 html、js、css 文件到 COS 的 project/foo 路径下
cos up 'dist/**/*.@(html|js|css)' project/foo
# 上传本地 dist 文件夹下的全部非 map 文件到 COS 的 project/foo 路径下
cos up dist project/foo --ignore 'dist/**/*.map'
配置介绍
coscmd
会从命令行参数、当前目录下的 cos.config.js
文件以及用户根目录下的 cos.config.js
文件中解析运行时所需的配置,从而决定如何上传文件。一个典型的 cos.config.js
配置文件如下:
// cos.config.js
module.exports = {
client: {
enable: true, // 是否启用
Bucket: "bucket-xxxx", // COS 存储桶的名称
Region: "ap-guangzhou", // COS 存储桶所在地域
SecretId: "***", // 腾讯云 SecretId
SecretKey: "***", // 腾讯云 SecretKey
cdn: { domain: "file.example.com" }, // 与 COS 关联的 CDN 的配置(未关联可不填)
},
upload: {
source: "dist/**", // 本地资源,支持单文件、文件夹、glob 表达式
ignore: ["dist/**/*.map"], // 要忽略文件的 glob 表达式
cwd: process.cwd(), // 查找 source 时的工作目录,默认是 process.cwd()
target: "project/foo", // 保存到 COS 的路径,默认是根路径
rename: false, // 是否对文件进行重命名,如何设置为 true 默认重命名为 16 个小写字母和数字的随机组合,设置为数字可以自定义长度
flat: false, // 是否铺平文件夹层级
showProgress: false, // 是否以进度条的形式展示上传过程
cdnPurgeCache: false, // 是否刷新 CDN 缓存
cdnPushCache: false, // 是否预热 CDN 缓存
dryRun: false, // 只模拟上传过程,不实际上传
},
};
你可以复制这段配置,在自己电脑的用户根目录下创建一个
cos.config.js
文件,来测试一下上面介绍到的cos upload
命令了,注意把其中的一些值替换为你自己 COS 的配置。
client
字段的作用是配置 COS
客户端及其关联的 CDN
,upload
字段的作用是配置上传行为。这两个字段可以是一个对象也可以是一个数组,如果是数组,则代表有多个客户端或者有多次不同的上传任务。接下来我们分别详细介绍这两部分的配置。
客户端(client
)配置
client
字段的完整 TS 类型定义为如下的 ClientConfig
:
import { COSOptions } from "cos-nodejs-sdk-v5";
import { ClientConfig as CDNClientConfig } from "tencentcloud-sdk-nodejs/tencentcloud/common/interface";
// COS 存储桶配置
export interface BucketParams {
Bucket: string;
Region: string;
}
export interface SingleClientConfig extends BucketParams, COSOptions {
// 是否启用这个客户端
enable?: boolean;
// client 名称,当有多个客户端时可以在执行命令行时通过 --client 参数指定要使用的客户端,不指定,使用全部 enable 的客户端
name?: string;
// COS 关联的 CDN 的相关配置
cdn?: {
domain: string; // CDN 加速域名
config?: CDNClientConfig; // 实例化 CDN Client 时的配置参数
};
}
export type ClientConfig = SingleClientConfig | SingleClientConfig[];
其中 COSOptions 是腾讯云 COS Node.js SDK 在实例化 COS
客户端时的参数,其中 CDNClientConfig 是 腾讯云 API Node.js SDK 在实例化 CDN
客户端时的参数,cdn.config
如果未指定,默认会复用 COSOptions
中的 SecretId
和 SecretKey
,请保证该密钥同时有 COS
和 CDN
的访问权限。
当前目录下的配置文件优先级高于用户根目录下的配置文件,所以你可以把 client
配置仅保存到用户根目录下的配置文件中,这样可以避免密钥等敏感信息出现在项目代码里。
得益于配置文件是 js
,你也可以使用环境变量,比如:
// cos.config.js
module.exports = {
client: [
{
/*...*/
SecretId: process.env.COS_SECRET_ID, // 腾讯云 SecretId
SecretKey: process.env.COS_SECRET_KEY, // 腾讯云 SecretKey
},
],
upload: [
/*...*/
],
};
你甚至可以通过 Promise 异步返回配置:
// cos.config.js
module.exports = async () => {
await new Promise((resolve) => setTimeout(resolve, 3000));
return {
client: [
/*...*/
],
upload: [
/*...*/
],
};
};
由于 COS
本身也支持使用临时密钥来初始化,你也可以这样设置
// cos.config.js
const axios = require("axios");
module.exports = {
client: [
{
/*...*/
// 使用临时密钥初始化 COS,参考 https://cloud.tencent.com/document/product/436/14048
getAuthorization: function (options, callback) {
axios({
method: "POST",
url: "https://example.com/api/cos/sts", // 伪地址,仅作示例
data: {
scope: options.Scope,
},
}).then((res) => {
const data = get(res, "data");
const credentials = get(data, "credentials");
if (credentials) {
callback({
TmpSecretId: credentials.tmpSecretId,
TmpSecretKey: credentials.tmpSecretKey,
SecurityToken: credentials.sessionToken,
StartTime: data.startTime,
ExpiredTime: data.expiredTime,
ScopeLimit: true,
});
} else {
console.error("cos credentials invalid");
}
});
},
},
],
upload: [
/* ... */
],
};
上传(upload
)配置
upload
字段的完整 TS 类型定义为如下的 UploadConfig
:
import {
PushUrlsCacheRequest,
PurgeUrlsCacheRequest,
} from "tencentcloud-sdk-nodejs/tencentcloud/services/cdn/v20180606/cdn_models";
export interface SingleUploadConfig {
source: string; // 本地资源,支持单文件、文件夹、glob 表达式
ignore: string[]; // 要忽略文件的 glob 表达式
cwd?: string; // 查找 source 时的工作目录,默认是 process.cwd()
target?: string; // 保存到 COS 的路径,默认是根路径
rename?: boolean | number; // 是否对文件进行重命名,如何设置为 true 默认重命名为 16 个小写字母和数字的随机组合,设置为数字可以自定义长度
flat?: boolean; // 是否铺平文件夹层级
showProgress?: boolean; // 是否以进度条的形式展示上传过程
cdnPurgeCache?: boolean | Omit<PurgeUrlsCacheRequest, "Urls">; // 是否刷新 CDN 缓存
cdnPushCache?: boolean | Omit<PushUrlsCacheRequest, "Urls">; // 是否预热 CDN 缓存
dryRun?: boolean; // 只模拟上传过程,不实际上传
preUpload?: (files: Pick<FileRes, "rPath" | "fullPath" | "cosKey">[]) => Promise<void>; // 开始上传前的钩子
postUpload?: (uploadRes: UploadRes) => Promise<void>; // 上传完成后的钩子
}
export type UploadConfig = SingleUploadConfig | SingleUploadConfig[];
其中 PurgeUrlsCacheRequest 和 PushUrlsCacheRequest 分别是 腾讯云 API Node.js SDK 在调用 CDN 缓存刷新和 CDN 缓存预热 API 时的参数,其中的 Urls
字段由 coscmd
根据上传的文件自动设置。
upload
字段和 client
字段一样,当前目录下的配置文件优先级高于用户根目录下的配置文件,所以你可以把 upload
配置在项目里,这样就可以为不同的项目设置不同的上传任务了。
upload
字段和 client
字段不同的地方在于,upload
中的值也可以通过命令行参数指定。使用方式如下:
Usage: cos upload|up [options] [source] [target]
上传本地文件到腾讯云 COS
Arguments:
source 要上传的本地资源,支持单文件、文件夹、glob 表达式
target 保存到 COS 的路径,默认是根路径
Options:
--rename [rename] 是否对文件进行重命名,如果为是,默认使用 16 个小写字母和数字的随机组合,指定数字可以自定义长度
--flat 是否展开文件夹层级
--show-progress 是否以进度条的形式展示上传过程
--cdn-purge-cache 是否刷新 CDN 缓存
--cdn-push-cache 是否预热 CDN 缓存
--dry-run 只模拟上传过程,不实际上传
-h, --help display help for command
支持多种配置方式的好处在于,你可以把可能包含敏感信息的 client
配置保存在用户根目录下,把和上传任务相关的配置保存在项目里或者在运行时指定。这样既方便给不同的项目设置不同的上传任务,也使得你可以在任意位置通过 cos up
命令上传任意文件到 COS
了。
upload
配置的优先级规则
命令行参数中指定的值会覆盖掉配置文件中的 upload
配置。比如配置文件中设置是 rename: false
,但是执行的命令是 cos up --renmae
,实际上传时文件依然会重命名。
需要注意的是:如果通过命令行指定了 source
,那么配置文件中的 upload
就会被忽略。比如 cos up logo.png
就会把本地的 logo.png
上传到 COS 的根目录下,无论当前项目或用户根目录下配置文件中的 upload
是什么。
source
与 target
介绍
source
支持填写单文件路径、文件夹路径、glob
表达式,解析 glob 表达式依赖的是 glob,其中 dot 和 nodir
参数为 true
,注意使用 glob
表达式时,需要加引号。
target
在上传单文件时,如果后缀和 source
相同,则作为文件名,比如 cos up logo.png foo/brand.png
上传后在 COS 中的位置为 foo/brand.png
。如果后缀不同或者没有后缀,则作为文件夹,比如 cos up logo.png bar/brand
上传后在 COS 中的位置为 bar/brand/logo.png
。
当 target
为文件夹或 glob 表达式时,参考下图中的说明:
最佳实践
一、前端项目打包完成后自动上传产物到 COS 并自动预热 CDN 缓存。
- 首先在项目中安装
coscmd
:npm i coscmd --save-dev
或yarn add coscmd -D
。 - 在项目中添加
coscmd
的运行时配置文件cos.config.js
- 按照前面介绍配置
client
的方式,选择一种安全的方式添加客户端,比如:
const pkg = require("./package.json");
module.exports = {
client: [
{
enable: true,
Bucket: "bucket-xxxx",
Region: "ap-guangzhou",
SecretId: process.env.COS_SECRET_ID, // 从环境变量中读取腾讯云 SecretId
SecretKey: process.env.COS_SECRET_KEY, // 从环境变量中读取腾讯云 SecretKey
cdn: { domain: "file.example.com" },
},
],
upload: [
{
source: "dist/**",
ignore: ["dist/**/*.map"], // 不上传 map 文件
cwd: __dirname,
target: `project/${pkg.name}`,
rename: false,
flat: false,
showProgress: false,
cdnPurgeCache: false,
cdnPushCache: true, // 上传完成后自动预热 CDN 缓存
dryRun: false,
async postUpload() {
// 上传结束后可以执行一些清理任务
},
},
],
};
- 在
package.json
中 添加npm scripts
,打包完成之后自动执行上传 COS 的任务。
{
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"postbuild": "cos up"
}
}
这样配置后,无论是本地打包还是和 CI
流水线集成,都能很方便的管理前端静态资源了。
Tips
- 执行
cos upload
命令时可以添加--dry-run
参数,这样coscmd
只会模拟上传过程,不会实际上传文件,方便查看都有哪些文件会被上传以及上传后的位置是什么了。 - 设置环境变量
DEBUG=coscmd
可以查看coscmd
的详细运行日志,包括解析到的配置文件内容,以及每个文件上传时腾讯云返回的错误和响应。 - 如果配置文件中的
client
数组的长度(enable: true
)是m
,upload
数组的长度是n
,最终的上传任务数会是m * n
,也就是说,每个客户端都会把每个上传任务执行一次。 - 当配置文件中有多个
enable
的客户端时,在执行命令时,可以使用--client
或者-c
参数指定要使用的客户端。不指定则全部enable
的客户端都会生效。 - 可以使用
--config-file
参数指定配置文件路径。