从钉盘同步文档到 TorchV AIS:简明教程
本文介绍如何使用钉钉 DWS 命令行工具,将钉盘或“文档空间”中的文件下载到本地中转目录,再上传到独立部署的 TorchV AIS 知识库。
本文适用于以下场景:
- 钉盘企业空间或“我的文件”中的普通文件;
- 钉盘文件夹的批量拉取;
- Word、Excel、PDF、PPT、Markdown 等文件导入 AIS;
- 后续扩展为定时、增量、可审计的单向同步任务。
本文中的“钉盘”是钉钉的文件存储层。钉钉在线文档、在线电子表格虽然也显示在文件目录中,但不能一律当作普通文件下载,需要按内容类型分别导出。
一、钉盘同步和知识库同步有什么不同
| 对比项 | 钉盘/文档空间 | 钉钉知识库 |
|---|---|---|
| 主要结构 | 空间、文件夹、文件 | 知识空间、目录节点、知识页面 |
| 空间标识 | spaceId | workspaceId |
| 根目录标识 | rootFolderId | 知识库根节点或节点ID |
| 文件标识 | dentryUuid / fileId | nodeId |
| 普通文件获取 | 使用 Drive 直接下载 | 普通附件下载,在线内容另行导出 |
| 整目录处理 | 支持 status、pull、push、sync | 通常需要遍历节点并逐个导出 |
| 推荐同步方向 | 钉盘 → 本地 → AIS | 知识库 → 本地 → AIS |
向 AIS 导入时,建议始终采用单向流程:
钉盘只读扫描
↓
识别文件与在线文档类型
↓
下载或导出到本地 staging 目录
↓
计算哈希并记录同步清单
↓
上传到 AIS 指定目录
↓
按 AIS 文档编码读回验证
不建议为这个场景使用 push 或双向 sync,以免把本地中转文件反向写回钉盘。
二、准备工作
1. 本地工具
沿用前一份钉钉知识库导入项目:
cd /Users/lu/Documents/Codex/dingtalk-ais-sync
SYNC_PROJECT="$(pwd)"
DWS_BIN="$SYNC_PROJECT/node_modules/.bin/dws"
AIS_KB_BIN="/Users/lu/Documents/Codex/.agents/bin/ais-kb.sh"
mkdir -p "$SYNC_PROJECT/staging/drive" "$SYNC_PROJECT/state"
检查 DWS 登录状态:
"$DWS_BIN" auth status --format json
应确认当前登录的是正确的钉钉企业,并且访问令牌有效。首次使用时执行:
"$DWS_BIN" auth login
本场景至少需要钉盘/文档空间的只读、列表和下载权限;如果存在在线文档,还需要对应的文档或电子表格导出权限。
2. AIS目标目录
本文继续以以下目录为例:
卢向东的个人知识库/钉钉知识库导入存放目录
检查目录:
"$AIS_KB_BIN" \
"kb tree 卢向东的个人知识库/钉钉知识库导入存放目录/ --depth 2 --limit 50"
三、发现钉盘空间
钉盘可能位于企业空间,也可能位于个人的“我的文件”。先根据实际位置选择一种查询方式。
1. 查询企业空间
"$DWS_BIN" wiki space list \
--type orgSpace \
--format json
如果返回 nextToken,应使用游标继续查询,直到分页结束。不要默认选择返回结果中的第一个空间。
2. 查询“我的文件”空间
"$DWS_BIN" wiki space list \
--type mySpace \
--format json
从真实返回中保存:
spaceId:钉盘空间ID;rootFolderId:空间根目录ID。
rootFolderId才能作为 Drive 的根文件夹参数;不要把知识库的workspaceId或数字型dentryId混用为文件夹ID。
四、浏览并定位目标文件夹
列出空间根目录:
"$DWS_BIN" drive +list \
--folder "<rootFolderId>" \
--limit 50 \
--format json
继续浏览某个子目录:
"$DWS_BIN" drive +list \
--folder "<子文件夹dentryUuid>" \
--limit 50 \
--format json
读取结果时应注意:
--folder使用dentryUuid或fileId,不是数字型dentryId;- 一页最多读取50项;
hasMore=true时应根据nextCursor继续分页;- 同名文件多于一个时,应根据目录、类型、大小和修改时间消歧,不能直接选择第一项。
如果手中只有一个钉盘文件链接,可以先解析链接:
"$DWS_BIN" drive info \
--node "<钉盘文件或文件夹URL>" \
--format json
以返回的真实 nodeId 继续操作。
五、下载普通文件
1. 检查文件类型
"$DWS_BIN" drive +inspect \
--node "<文件dentryUuid>" \
--format json
普通 Office、PDF、图片、压缩包等文件可直接下载;在线文档类型需要走第七节的分类导出。
2. 下载到本地中转目录
单文件下载的输出路径使用当前工作目录下的相对路径:
cd "$SYNC_PROJECT"
"$DWS_BIN" drive +download \
--node "<文件dentryUuid>" \
--output "staging/drive/文件名.pdf" \
--format json
下载后验证:
file "staging/drive/文件名.pdf"
shasum -a 256 "staging/drive/文件名.pdf"
至少确认文件存在且大小大于0。源端和下载结果都提供可比哈希时,再进一步比较校验和。
六、批量拉取整个钉盘文件夹
DWS 支持比较和拉取普通文件夹。文件夹命令使用本地绝对路径。
1. 只读比较
"$DWS_BIN" drive status \
--local-folder "$SYNC_PROJECT/staging/drive" \
--remote-folder "<钉盘文件夹dentryUuid>" \
--format json
结果通常分为:
new_remote:钉盘有、本地没有;new_local:本地有、钉盘没有;modified:两侧内容不同;unchanged:内容一致;unknown:无法可靠判断。
2. 预演拉取
"$DWS_BIN" drive pull \
--local-folder "$SYNC_PROJECT/staging/drive" \
--remote-folder "<钉盘文件夹dentryUuid>" \
--if-exists skip \
--dry-run \
--format json
skip 是安全默认值:本地已存在同名文件时不覆盖。检查预演结果无误后,再用完全相同的目录和冲突策略正式执行。
3. 正式拉取
"$DWS_BIN" drive pull \
--local-folder "$SYNC_PROJECT/staging/drive" \
--remote-folder "<钉盘文件夹dentryUuid>" \
--if-exists skip \
--format json
如果运行时要求确认,应在核对目标文件夹、同步方向和影响后,按命令提示确认。不要为了省事默认改为 overwrite。
注意:
- 文件夹拉取只处理普通文件和目录;
- 在线文档、在线电子表格和快捷方式不会按普通二进制文件同步;
- 拉取不会删除本地多余文件;
- 应检查汇总和逐项结果,存在
failed或unknown时不能宣称全部成功。
七、处理钉盘中的在线文档
钉盘目录中的节点需要先按类型分流:
| 节点类型 | 正确处理方式 |
|---|---|
普通 docx、xlsx、pdf、pptx 等 | dws drive +download |
钉钉在线文字文档 adoc | dws doc +export,建议导出为 DOCX 或 Markdown |
钉钉在线电子表格 axls | dws sheet export,导出为 XLSX |
AI表格 able | 使用 AI 表格专用导出流程 |
在线文字文档示例:
"$DWS_BIN" doc +export \
--node "<在线文档nodeId>" \
--export-format docx \
--output "./staging/drive/文档名.docx" \
--format json
在线电子表格示例:
"$DWS_BIN" sheet export \
--node "<在线表格nodeId>" \
--output "./staging/drive/表格名.xlsx" \
--format json
这部分与“钉钉知识库文档导出到 AIS”的类型分流方法相同,可结合项目目录中的前一份教程阅读:
钉钉知识库文档导出到AIS知识库教程.md
八、上传到 AIS
下载或导出成功后,将文件逐个上传到 AIS 目标目录:
"$AIS_KB_BIN" \
--upload-file "$SYNC_PROJECT/staging/drive/文件名.pdf" \
--path-name "/卢向东的个人知识库/钉钉知识库导入存放目录"
每次上传后保存 AIS 返回的稳定文档编码。然后检查目录:
"$AIS_KB_BIN" \
"kb tree 卢向东的个人知识库/钉钉知识库导入存放目录/ --depth 2 --limit 50"
待 AIS 完成解析和知识加工后,按文档编码读回:
"$AIS_KB_BIN" \
"kb cat --code <AIS文档编码> --head 120"
只有同时满足以下条件,才能认为单个文件完成了端到端导入:
- 钉盘文件下载或在线内容导出成功;
- 本地文件存在且大小正常;
- AIS 返回稳定文档编码;
- 文件出现在目标目录;
- AIS 可以读取知识加工后的正文。
九、建立同步清单
建议为每个文件保存一条映射记录:
{
"sourceSystem": "dingtalk-drive",
"spaceId": "<钉盘spaceId>",
"sourceFolderId": "<钉盘文件夹dentryUuid>",
"sourceNodeId": "<文件dentryUuid>",
"sourceName": "文件名.pdf",
"sourceType": "file",
"sourceUpdatedAt": "2026-08-24T10:00:00+08:00",
"sourceSizeBytes": 123456,
"localFile": "staging/drive/文件名.pdf",
"sha256": "<本地文件SHA-256>",
"aisDirectoryCode": "<AIS目录编码>",
"aisDocumentCode": "<AIS文档编码>",
"syncStatus": "SUCCESS"
}
后续增量同步应以 sourceNodeId 为源对象主键,结合修改时间、大小和本地哈希判断是否变化,不能只依赖文件名。
十、从一次性导入升级为每日同步
生产化任务可以按以下步骤运行:
定时触发
→ 读取目标钉盘文件夹
→ 完成全部分页
→ 与上次同步清单比较
→ 只下载新增或已修改文件
→ 在线文档按类型导出
→ 上传 AIS
→ 读回验证
→ 更新映射、日志和失败队列
建议增加以下控制:
- 最小权限:生产环境使用企业内部应用,只开放所需只读权限;
- 范围限制:明确允许同步的空间和根文件夹,避免无界扫描;
- 增量同步:优先处理新增和修改文件;
- 幂等映射:保存钉盘
sourceNodeId与 AIS 文档编码的对应关系; - 失败重试:网络中断、导出超时和 AIS 转换中分别处理;
- 删除策略:钉盘源文件被删除时,默认只告警,不自动删除 AIS 文件;
- 权限治理:钉盘与 AIS 权限模型不完全相同,敏感目录应单独映射和审核;
- 审计记录:记录同步时间、操作者、源文件、目标目录、哈希和最终状态。
十一、常见问题
1. 为什么 drive pull 没有拉到在线文档
文件夹拉取只处理普通文件和目录。在线文字文档、在线表格等需要识别类型后,使用相应的导出命令。
2. spaceId、rootFolderId 和 workspaceId 能否混用
不能。spaceId 表示钉盘空间,rootFolderId 表示钉盘根文件夹,workspaceId 表示知识库空间。后续参数必须使用接口实际返回的正确ID。
3. 同名文件应该怎么处理
不要根据名称自动选择第一项。应结合完整目录、dentryUuid、文件类型、大小和更新时间确定唯一源文件。
4. 是否应该使用双向同步
钉盘导入 AIS 的目标是知识接入,不是文件协同。推荐只执行“钉盘 → 本地 → AIS”,避免使用 push 或双向 sync。
5. 钉盘删除文件后,是否自动删除 AIS 内容
初期不建议自动删除。应先记录删除事件并告警,由管理员确认 AIS 中的知识是否仍需保留;生产阶段再建立明确的软删除、归档和审计策略。
十二、最短命令清单
# 1. 发现钉盘空间
"$DWS_BIN" wiki space list --type orgSpace --format json
# 2. 浏览目标文件夹
"$DWS_BIN" drive +list --folder "<folderId>" --limit 50 --format json
# 3. 查看文件类型
"$DWS_BIN" drive +inspect --node "<nodeId>" --format json
# 4. 下载普通文件
"$DWS_BIN" drive +download \
--node "<nodeId>" \
--output "staging/drive/文件名" \
--format json
# 5. 或批量拉取文件夹:先预演,再执行
"$DWS_BIN" drive pull \
--local-folder "$SYNC_PROJECT/staging/drive" \
--remote-folder "<folderId>" \
--if-exists skip \
--dry-run \
--format json
"$DWS_BIN" drive pull \
--local-folder "$SYNC_PROJECT/staging/drive" \
--remote-folder "<folderId>" \
--if-exists skip \
--format json
# 6. 上传 AIS
"$AIS_KB_BIN" \
--upload-file "$SYNC_PROJECT/staging/drive/文件名" \
--path-name "/卢向东的个人知识库/钉钉知识库导入存放目录"
# 7. 读回验证
"$AIS_KB_BIN" "kb cat --code <AIS文档编码> --head 120"
本教程适合先完成一次小范围验证。正式接入时,应在固定文件夹、最小权限、增量清单、失败重试和人工删除确认的基础上,再配置定时任务。
- 一、钉盘同步和知识库同步有什么不同
- 二、准备工作
- 1. 本地工具
- 2. AIS目标目录
- 三、发现钉盘空间
- 1. 查询企业空间
- 2. 查询“我的文件”空间
- 四、浏览并定位目标文件夹
- 五、下载普通文件
- 1. 检查文件类型
- 2. 下载到本地中转目录
- 六、批量拉取整个钉盘文件夹
- 1. 只读比较
- 2. 预演拉取
- 3. 正式拉取
- 七、处理钉盘中的在线文档
- 八、上传到 AIS
- 九、建立同步清单
- 十、从一次性导入升级为每日同步
- 十一、常见问题
- 1. 为什么
drive pull没有拉到在线文档 - 2.
spaceId、rootFolderId和workspaceId能否混用 - 3. 同名文件应该怎么处理
- 4. 是否应该使用双向同步
- 5. 钉盘删除文件后,是否自动删除 AIS 内容
- 十二、最短命令清单