112 lines
7.8 KiB
Markdown
112 lines
7.8 KiB
Markdown
# 本地备份同步七牛
|
||
|
||
独立 Node.js 脚本项目,使用官方 qiniu SDK 7.15.2。入口命令在 doodle-store 根目录执行。只复制本地文件到已存在的七牛空间,不创建空间、不删除/覆盖远端对象、不修改数据库或业务 URL。
|
||
|
||
## 配置
|
||
|
||
已生成本机 `packages/asset-sync/.env`,源目录配置为:
|
||
|
||
```dotenv
|
||
SOURCE_DIR=/Users/joey-xd/sites/doodle/doodle-assets/cloud_backup
|
||
QINIU_AK=
|
||
QINIU_SK=
|
||
QINIU_BUCKET=
|
||
QINIU_REGION=
|
||
QINIU_KEY_PREFIX=doodle/
|
||
QINIU_PUBLIC_DOMAIN=
|
||
SYNC_CONCURRENCY=3
|
||
SYNC_RETRIES=2
|
||
SYNC_MAX_FILE_BYTES=67108864
|
||
```
|
||
|
||
填写本地 `.env` 即可,不要将 AK/SK 写到小程序、Git、命令参数或聊天中。该文件被 Git 忽略,并以 0600 权限保存。新机器可从 `.env.example` 复制;相对 SOURCE_DIR 以配置文件目录为基准,运行目录不影响源路径。进程环境变量优先于文件配置。
|
||
|
||
| 配置 | 说明 |
|
||
| ------------------- | -------------------------------------------------------------------------------------------------------------------------- |
|
||
| SOURCE_DIR | 本地备份根目录,工具只读 |
|
||
| QINIU_AK / QINIU_SK | 七牛服务端 AccessKey / SecretKey,仅正式同步要求 |
|
||
| QINIU_BUCKET | 所有资源共用的公开空间:图片、头像、字体、JSON 等 |
|
||
| QINIU_REGION | 可留空自动查询;固定区域时使用七牛 region ID,如 z0、z1、z2、na0、as0 |
|
||
| QINIU_KEY_PREFIX | 对象前缀;默认 doodle/,空串为原相对路径 |
|
||
| QINIU_PUBLIC_DOMAIN | 可选 HTTPS origin,例如 https://cdn.example.com;不含 /doodle 等路径,仅用于生成报告中的公共 URL,不证明域名已经绑定该空间 |
|
||
| SYNC_CONCURRENCY | 并发文件数,1~10,默认 3 |
|
||
| SYNC_RETRIES | 瞬时错误额外重试次数,0~5,默认 2 |
|
||
| SYNC_MAX_FILE_BYTES | 每个文件读取内存的大小限制,默认 64 MiB |
|
||
|
||
空间必须已存在且有权查询和上传。执行前读取空间设置,核对目标空间实际 private=0,工具不会自动调整 ACL。头像与其他资源使用同一个 QINIU_BUCKET,无需配置私有空间。
|
||
|
||
## 使用
|
||
|
||
```bash
|
||
# 查看用法
|
||
pnpm assets:sync --help
|
||
|
||
# 默认预演全部文件,不调用七牛接口,也不要求 AK/SK
|
||
pnpm assets:sync
|
||
|
||
# 只预演题型预览图
|
||
pnpm assets:sync --only assets/previews
|
||
|
||
# 填写 .env 后,先同步 51 张预览
|
||
pnpm assets:sync --apply --only assets/previews
|
||
|
||
# 可选择多个目录
|
||
pnpm assets:sync --apply --only assets/fonts --only assets/materials
|
||
|
||
# 全部同步,含头像,均使用 QINIU_BUCKET 公开空间
|
||
pnpm assets:sync --apply
|
||
|
||
# 自定义配置文件/报告;报告文件不能已存在,也不能位于源备份内
|
||
pnpm assets:sync --env /绝对路径/.env.sync --report /绝对路径/report.json
|
||
```
|
||
|
||
`--only` 按目录前缀或精确文件路径筛选,不是 glob;`--dry-run` 可显式声明预演,与 `--apply` 互斥。通过默认预演确认清单后,再添加 --apply 上传。文件缺失、损坏 JSON、超限文件、软链接及无法识别的预览/头像图片会停止预检。
|
||
|
||
## 对象路径和同步行为
|
||
|
||
默认映射:
|
||
|
||
```text
|
||
assets/previews/math/number-find.jpg
|
||
→ 公共 bucket : doodle/assets/previews/math/number-find.jpg
|
||
user-avatars/<文件名>.png
|
||
→ 同一公共 bucket : doodle/user-avatars/<文件名>.png
|
||
```
|
||
|
||
头像保留 `user-avatars/` 相对路径,与预览等资源共用公开空间。配置 QINIU_PUBLIC_DOMAIN 后,报告也会生成头像的公开地址。工具不根据文件名推断用户身份,用户归属仍需在后续绑定时核实。
|
||
|
||
1. 扫描源目录,忽略隐藏文件,记录实际 MIME、字节数、SHA-256 与七牛 ETag;不修改源文件。
|
||
2. 正式执行时重新读取并核对本地摘要,使用该次读取的 Buffer 上传,避免核对后源文件被修改。
|
||
3. 远端不存在时,用指定 bucket:key 的 insertOnly=1 凭证上传,仅允许新增,启用 SDK CRC 校验和 HTTPS。
|
||
4. 远端同 key 且 ETag/大小一致:跳过并标记已核对。不同内容:报告 conflict,保留原远端文件;需要新版本时选择新的前缀/key。
|
||
5. 上传完成再次 stat,对比远端 ETag/大小;不是仅凭“请求成功”就记完成。
|
||
6. 瞬时网络错误、429、5xx 有限重试,鉴权错误和冲突不盲目重试。上传已成功但响应丢失时,重试遇到 614 后回查摘要恢复。
|
||
7. 任一文件失败或冲突时命令退出码为 1,其余文件结果仍写入报告。中断后重新运行同一命令,会重新检查远端并跳过已完成对象;未提供分片级断点续传。
|
||
|
||
校验方式是七牛内容 ETag 和大小,不等同于从 CDN 下载全部文件后比较 SHA-256。SHA-256 是本地备份摘要,报告明确记录 verifiedBy=qiniu-etag-and-size。不会自动刷新 CDN 或替换同名对象。
|
||
|
||
## 报告与后续接入
|
||
|
||
默认报告写 `packages/asset-sync/reports/<时间>-<随机ID>.json`,目录被 Git 和格式化工具忽略,文件权限 0600;含源相对路径、目标 bucket/key、MIME、大小、摘要、状态和有限错误码。不包含 AK、SK、上传凭证、签名链接或 SDK 原始异常。中断时报告可能未写完,以重新运行后的远端校验为准。
|
||
|
||
主要状态:planned(预演)、uploaded(上传并核对)、skipped(已有同内容)、conflict(同名异内容)、failed、not_attempted(全批配置/权限预检未通过)。常见全批错误:CREDENTIALS_REQUIRED、BUCKET_REQUIRED、BUCKET_VISIBILITY_MISMATCH。上传用户需有 bucketInfo、stat、upload 所需权限。
|
||
|
||
这次只做文件同步。同步成功后仍需按报告映射更新新后端 assets(保持现有 ID 并回填 bucket/key/MIME/摘要、status=ready)、字体配置、用户头像绑定及首页 JSON 内的 cloud 引用。content/page-config.json 当前会原样复制,不会自动转换嵌套链接;原云上传和定时任务也不会自动切换到七牛。
|
||
|
||
## 验证与当前预演
|
||
|
||
```bash
|
||
pnpm assets:test
|
||
pnpm check
|
||
```
|
||
|
||
测试使用临时本地文件和模拟七牛接口,覆盖配置、ETag 边界、头像同空间映射、预演无网络、首次上传、重复跳过、冲突保护、重试、响应丢失恢复、源文件变化、校验失败、凭据脱敏及 CLI 报告权限。没有使用真实 AK/SK 或执行真实上传。
|
||
|
||
本地备份预演:62 个文件,共 3,568,778 字节;其中题型预览 51、头像 7、字体 1、素材 1、首页配置 1、demo 1。该数量为本地预演结果,不代表已上传。
|
||
|
||
实现依据:[七牛官方 Node.js SDK](https://developer.qiniu.com/kodo/sdk/nodejs)、[七牛上传策略](https://developer.qiniu.com/kodo/manual/put-policy)。
|
||
|
||
## 回填服务端资产
|
||
|
||
上传报告确认成功后,根目录执行 `pnpm assets:map --report /绝对路径/报告.json` 预演,再添加 `--apply` 写入本机 doodle_dev。该独立回填步骤会重新核对七牛对象与备份摘要,事务更新已有题型预览资产,保留资源 ID 并记录审计;不处理头像归属、首页 JSON 嵌套链接或其他资源绑定。配置必须与 server 的域名、前缀及空间一致,详见根 README。
|