news 2026/9/21 14:23:34

飞书 CLI `docs +media-download` 完全指南:下载文档素材与画板缩略图

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
飞书 CLI `docs +media-download` 完全指南:下载文档素材与画板缩略图

飞书 CLIdocs +media-download完全指南:下载文档素材与画板缩略图

【免费下载链接】cliThe official Lark/飞书 CLI tool, maintained by the larksuite team — built for humans and AI Agents. Covers core business domains including Messenger, Docs, Base, Sheets, Calendar, Mail, Tasks, Meetings, and more, with 200+ commands and 20+ AI Agent Skills.项目地址: https://gitcode.com/gh_mirrors/cli414/cli

导读:本文以 lark-cli 官方技能文档 lark-doc-media-download.md 为主体,系统讲解docs +media-download命令的使用场景、参数语义、底层 API 调用链与扩展名自动补全机制。读完本文,你将掌握从飞书云文档中提取图片/文件素材 token 并安全下载到本地的完整流程,理解mediawhiteboard两种资源类型的差异,并能独立排障权限(HTTP 403)与限流错误。

命令定位:它解决什么问题

docs +media-download是 lark-cli 中负责下载文档内嵌资源的命令,覆盖两类资源:

  • 文档素材(media):文档中引用的图片或文件附件,通过file_token定位;
  • 画板缩略图(whiteboard):白板(画板)页面的缩略图,通过whiteboard_id定位。

它的核心特性是:当--output指定的路径不带扩展名时,命令会根据响应头的Content-Type(或Content-Disposition中的文件名)自动补全扩展名,避免手动猜测文件类型。

在源码中,该命令被注册为Service: "docs"Command: "+media-download"Risk: "read"(只读操作),定义于 shortcuts/doc/doc_media_download.go,并挂载在docs命令组下(见 shortcuts/doc/shortcuts.go)。

选择规则:download 与 preview 如何取舍

同一文档素材存在两个高度相关的命令,需要按用户意图区分:

场景使用命令
用户明确说“下载素材”docs +media-download
用户只是想查看、预览图片或文件素材优先使用docs +media-preview
目标明确是画板 / whiteboard / 画板缩略图docs +media-download --type whiteboard+media-preview不支持画板)

从源码实现看,两个命令底层都调用了扩展名自动补全逻辑autoAppendDocMediaExtension(shortcuts/doc/doc_media_ext.go),但+media-preview仅支持file_token素材,不提供--type whiteboard分支;而+media-downloadwhiteboard分支会调用完全不同的 API(详见下文“底层调用链”)。

命令用法:三种典型场景

# 场景一:下载图片/文件素材(默认 type=media) lark-cli docs +media-download --token "Z1Fjxxxxxxxx" --output ./asset # 场景二:指定输出文件名(带扩展名则不会自动补全) lark-cli docs +media-download --token "Z1Fjxxxxxxxx" --output ./asset.png # 场景三:下载画板缩略图(whiteboard token) lark-cli docs +media-download --type whiteboard --token "wbcnxxxxxxxx" --output ./whiteboard

关于“带扩展名不补全”的细节

源码 doc_media_download.go 展示了补全前的处理逻辑:

  • whiteboard类型有兜底扩展名fallbackExt = ".png"(画板缩略图必然是 PNG);
  • media类型没有兜底,必须依赖响应头推断;
  • --outputfilepath.Ext判定为“已有显式扩展名”(且不是孤立的.),则跳过补全,直接按原路径保存;
  • 若路径以尾点xxx.结尾,会先去掉尾点再补全(例如typed.typed.csv),这一行为由测试 TestDocMediaDownloadAppendsExtensionForTrailingDotOutput 验证。

参数详解:必填项与可选语义

原文档的参数表如下:

参数必填说明
--token <token>资源 token:素材为file_token,画板为whiteboard_id
--output <path>本地保存路径;不带扩展名会自动补全
--type <type>media(默认)或whiteboard

结合源码 doc_media_download.go 的 Shortcut 定义,还有两个原文档未列出的重要参数:

参数必填说明
--overwrite否(bool)是否覆盖已存在的输出文件。默认不覆盖:若目标文件已存在,命令返回FailedPrecondition错误并提示“use --overwrite to replace”
--as身份选择:userbot。该命令的AuthTypes声明为["user", "bot"]--as user代表用户本人下载,--as bot代表应用身份下载

参数校验与安全约束

执行时会先做两类校验(doc_media_download.go):

  1. token 校验validate.ResourceName(token, "--token")校验资源名合法性,失败返回InvalidArgument
  2. 输出路径安全校验runtime.ResolveSavePath(outputPath)只接受相对路径。这与共享规则一致——lark-shared 明确规定--file--output等路径参数只接受 cwd 下的相对路径,传绝对路径会报unsafe file path(详见 skills/lark-shared/SKILL.md 安全规则第 5 条)。补全扩展名后的最终路径同样会再次校验。

下载完成后,命令以 JSON 形式输出结果(doc_media_download.go):

{ "saved_path": "./asset.png", "size_bytes": 20480, "content_type": "image/png" }

底层调用链:两条 API 路径

--type决定最终请求的 OpenAPI 端点,这一逻辑在 doc_media_download.go 中明确:

  • --type media(默认):GET /open-apis/drive/v1/medias/{token}/download
  • --type whiteboardGET /open-apis/board/v1/whiteboards/{token}/download_as_image

两者的差异不仅在端点,还体现在权限预检上:

  • media模式在下载前会调用common.CheckDriveFileExportPermission(runtime, token)检查当前身份是否具备文档素材的导出权限(对应 dry-run 中的第一步请求GET /open-apis/drive/v1/permissions/{token}/members/auth?type=file&action=export);
  • whiteboard模式跳过导出权限预检,直接请求画板下载端点。

这些差异可由 dry-run 输出与测试验证:

  • TestDocMediaDownloadDryRunIncludesExportAuthBeforeDownload 断言media模式 dry-run 包含 2 个 API:先导出权限检查、后媒体下载;
  • TestDocWhiteboardDownloadDryRunSkipsExportAuth 断言whiteboard模式 dry-run 只有 1 个 API(/open-apis/board/v1/whiteboards/.../download_as_image)。

dry-run 预览能力来自 Shortcut 的DryRun字段(doc_media_download.go),配合 lark-shared 安全规则“目标命令支持--dry-run时,用--dry-run预览危险请求”,是调用前的推荐动作。

权限与 scope

该命令声明的权限 scope 为docs:document.media:download,并带有一个条件 scopeDrivePermissionMemberAuthScope(仅当需要导出权限检查时才会触发)。ConditionalScopes的存在意味着:对某些身份/资源,命令可能额外需要 Drive 成员权限,相关断言见 TestDocMediaDownloadDeclaresConditionalPermissionMemberAuthScope。

扩展名自动补全:完整优先级链

autoAppendDocMediaExtension(shortcuts/doc/doc_media_ext.go)按如下优先级推断扩展名:

  1. 显式扩展名优先--output已含非空扩展名(非.)时直接返回,不做任何推断;
  2. Content-Type 映射:解析响应头Content-Type,查表docMediaMimeToExt(doc_media_ext.go),覆盖常见类型,例如image/png → .pngimage/jpeg → .jpgapplication/pdf → .pdftext/csv → .csvvideo/mp4 → .mp4application/vnd.openxmlformats-officedocument.wordprocessingml.document → .docx等;
  3. Content-Disposition 文件名:若 Content-Type 未命中,则从Content-Disposition: attachment; filename="..."中提取原文件名扩展名;
  4. 兜底扩展名:仅whiteboard类型使用.png兜底;media类型若无命中则保持原路径不变。

测试 TestDocMediaDownloadAppendsExtensionFromContentTypeMapping 与 TestDocMediaDownloadAppendsExtensionFromContentDispositionFilename 分别验证了第 2、3 条路径(后者模拟了Content-Type: application/octet-stream无法映射、但Content-Dispositiondrive_registry_config_addition.csv文件名时补全为.csv的场景)。

token 从哪里来:配合lark-doc-fetch使用

素材 token 最常见的来源是lark-cli docs +fetch返回的文档内容。使用--doc-format xml(默认)时,内嵌资源会以 XML 标签形式出现(详见 lark-doc-fetch.md 中“处理文档内嵌资源”一节):

  • 图片:<img token="..." .../>
  • 文件:<source token="..." name="..."/>
  • 画板:<whiteboard token="..."/>

提取规则(与 fetch 文档一致):

  • 标签内url属性时,仅当其为可信的公开 HTTPS URL(拒绝 userinfo、私有/回环/链路本地/组播/未指定地址 host)才可直接下载;
  • url时提取token:预览用docs +media-preview,下载用docs +media-download
  • <whiteboard>一律提取 token 后走docs +media-download(fetch 文档明确指示画板不用 preview)。

由此形成完整工作流:

# 第一步:获取文档内容,提取 token lark-cli docs +fetch --doc "文档URL或token" --doc-format xml # 第二步:根据提取的 token 下载素材 lark-cli docs +media-download --token "Z1Fjxxxxxxxx" --output ./asset

排障:两类典型错误

1. 权限错误:permission_denied与 HTTP 403

当导出权限预检失败时,命令返回permission_denied;当下载请求本身返回HTTP 403时,错误处理器withDocMediaDownloadRecoveryHint(shortcuts/doc/doc_errors.go)会在保留原始错误的同时,在hint中追加恢复指引:

Direct document media download returned HTTP 403. To preview the image or file content, trylark-cli docs +media-preview --token <MEDIA_TOKEN> --output <path>.

也就是说:遇到 403 时按 hint 改用docs +media-preview预览内容(见 lark-doc-media-preview.md),这是文档推荐的降级路径。注意两点实现细节:

  • 该 403 恢复提示仅对media类型生效:whiteboard 走的是独立 API,withDocMediaDownloadRecoveryHint明确不把画板下载重定向到 media-preview;
  • 导出权限检查若返回的是权限类错误(如LarkErrAppScopeNotEnabledLarkErrTokenNoPermissionLarkErrUserScopeInsufficient),命令会打印 warning 后继续下载而不是直接中止(doc_media_download.go),相关行为由 TestDocMediaDownloadPermissionAuthScopeErrorsWarnAndContinue 验证;只有检查结果为“明确无权限”(allowed == false)时才在下载前中止。

2. 限流错误:停止立即重试,指数退避

限流判定涵盖三类信号(doc_errors.go):错误子类型SubtypeRateLimit、业务错误码99991400、HTTP 状态码429。命中后 hint 会追加:

Document media download was rate limited; stop immediate retries and retry later with exponential backoff.

即:停止立即重试,稍后按指数退避重试。相关测试包括 TestDocMediaDownloadHTTP429SuggestsBackoff、TestDocMediaDownloadExportAuthRateLimitPreservesAPIErrorAndSuggestsBackoff 等。

其他值得注意的行为

  • 覆盖保护:默认若目标文件已存在则拒绝写入(FailedPrecondition),需要显式加--overwrite。该行为由 TestDocMediaDownloadRejectsOverwriteWithoutFlag 验证,且覆盖检查发生在扩展名补全之后(对最终路径判断);
  • HTTP 错误先于落盘暴露:请求失败时不会创建半截文件,见 TestDocMediaDownloadRejectsHTTPErrorBeforeWrite;
  • 导出被拒在下载前拦截:权限预检不通过时直接报错,避免无谓请求,见 TestDocMediaDownloadExportDeniedFailsBeforeDownload;
  • 身份模型:命令支持user/bot两种身份,--as的选择逻辑与身份权限差异(bot 查用户资源返回空成功而非报错)参见 skills/lark-shared/SKILL.md。

参考文档

  • lark-doc-fetch — 获取文档内容,用于提取素材/画板 token
  • lark-doc-media-preview — 预览素材(403 降级路径、与 download 的选择区分)
  • lark-shared — 认证、--as身份模型、相对路径安全规则与 JSON 输出契约

【免费下载链接】cliThe official Lark/飞书 CLI tool, maintained by the larksuite team — built for humans and AI Agents. Covers core business domains including Messenger, Docs, Base, Sheets, Calendar, Mail, Tasks, Meetings, and more, with 200+ commands and 20+ AI Agent Skills.项目地址: https://gitcode.com/gh_mirrors/cli414/cli

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/21 14:23:26

Ubuntu 20.04 离线安装 Realtek RTL8852BE 无线网卡驱动实战

装过 Linux 的朋友基本都有类似遭遇&#xff1a;系统装好了&#xff0c;界面也正常&#xff0c;结果右上角偏偏没有 WiFi 图标。尤其是一台崭新的笔记本&#xff0c;或者刚换的 USB 无线网卡&#xff0c;插上去一点反应没有&#xff0c;那一刻的心情真的有点崩溃。这次要聊的就…

作者头像 李华
网站建设 2026/9/21 14:23:05

Flutter图标颜色在鸿蒙系统的适配方案

1. 项目背景与核心挑战在跨平台开发领域&#xff0c;Flutter框架因其高效的渲染性能和丰富的组件库而广受欢迎。而鸿蒙系统作为新兴的操作系统平台&#xff0c;其设计理念和实现机制与传统Android/iOS存在显著差异。当开发者尝试将现有Flutter应用迁移到鸿蒙平台时&#xff0c;…

作者头像 李华
网站建设 2026/9/21 14:19:27

Mirror网络库自定义生成函数实战指南

1. Mirror网络库自定义生成函数深度解析在多人联机游戏开发中&#xff0c;对象生成与销毁是最基础也最关键的环节之一。Mirror作为Unity的高性能网络库&#xff0c;默认提供了简单的预制体实例化机制&#xff0c;但在实际项目中&#xff0c;我们往往需要更精细的控制——比如对…

作者头像 李华
网站建设 2026/9/21 14:08:54

VibeCoding 做历史粘贴板,Claude Code 的模型通道走 TaoToken

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/21 14:04:18

SSM框架实现健身房数字化管理系统设计与优化

1. 项目概述&#xff1a;当健身房遇上数字化管理去年帮本地一家中型健身房改造会员系统时&#xff0c;我深刻体会到传统纸质登记表的痛点——教练排课冲突、会员预约信息丢失、打卡记录混乱等问题频发。这个基于SSM框架的健身房管理系统&#xff0c;正是为了解决这些行业普遍存…

作者头像 李华