Install any skill in seconds. Free to start, no credit card required.
Get Started Free →基于飞书官方 API 的云盘管理技能,支持文件列表查询、上传、下载、文件夹创建、权限管理、文件搜索、统计信息、快捷方式、复制移动等完整功能。参考 feishu-drive 技能开发,修复了原技能中的 API 调用错误,并新增了自动化权限管理功能。
| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 212% | 0% |
| case-05 | ✗→✓ | ▲ Improved | 133% | 0% |
| case-07 | ✗→✓ | ▲ Improved | 126% | 0% |
| case-08 | ✗→✓ | ▲ Improved | 276% | 0% |
| case-14 | ✗→✓ | ▲ Improved | 229% | 0% |
本技能参考了社区中的 feishu-drive 技能,但在实现过程中发现原技能存在以下问题:
GET /open-apis/drive/v1/files/:token/children 应改为 drive/explorer/v2 版本)因此基于飞书官方文档重新开发了此技能,修复了所有已知问题,并新增了权限管理功能。
你是飞书云盘管理专家,负责通过飞书官方 API 实现文件列表查询、上传、下载和文件夹管理。
设置环境变量:
bashexport FEISHU_APP_ID="your_app_id" export FEISHU_APP_SECRET="your_app_secret" export FEISHU_ROOT_FOLDER_TOKEN="your_folder_token" # 可选:指定默认根目录
在使用技能之前,先指定一个根目录,后续所有操作都以此目录为基准:
pythonfrom feishu_drive_client import create_client, FeishuDriveClient import os # 方式1:使用便捷函数(推荐) # 自动从环境变量 FEISHU_APP_ID, FEISHU_APP_SECRET, FEISHU_ROOT_FOLDER_TOKEN 读取 client = create_client() # 方式2:手动创建客户端,从环境变量读取 client = FeishuDriveClient( app_id=os.getenv("FEISHU_APP_ID"), app_secret=os.getenv("FEISHU_APP_SECRET"), root_folder_token=os.getenv("FEISHU_ROOT_FOLDER_TOKEN") # 可选 ) # 方式3:手动指定所有参数 client = FeishuDriveClient( app_id="your_app_id", app_secret="your_app_secret", root_folder_token="your_folder_token" # 可选 ) # 方式4:后续动态设置根目录 client = FeishuDriveClient(app_id, app_secret) client.set_root_folder("your_folder_token")
设置根目录后,所有操作默认在根目录下进行:
python# 在根目录下创建子文件夹(无需传入 folder_token) result = client.create_folder("新文件夹") # 在根目录下上传文件 result = client.upload_file("/path/to/file.jpg") # 列出根目录内容 result = client.list_folder() # 如需操作其他目录,可临时指定 folder_token result = client.create_folder("其他位置的文件夹", parent_folder_token="其他token")
优先级规则:传入的 folder_token > 设置的 root_folder_token > 空字符串(根目录)
| 项目 | 值 | |------|---| | Base URL | https://open.feishu.cn/open-apis/drive/v1 | | 认证方式 | Authorization: Bearer {tenant_access_token} | | Content-Type | application/json (文件上传用 multipart/form-data) |
接口说明: 获取用户"我的空间"根文件夹的元数据
GET /open-apis/drive/explorer/v2/root_folder/meta响应示例:
json{ "code": 0, "data": { "token": "nodcnXXXXXX", "id": "7110173013420512356", "user_id": "7103496998321312356" }, "msg": "success" }
注意事项:
drive:drive 或 drive:drive.metadata:readonly接口说明: 在指定父文件夹下创建新文件夹
POST /open-apis/drive/v1/files/create_folder请求参数:
json{ "name": "文件夹名称", "folder_token": "父文件夹token" }
响应示例:
json{ "code": 0, "data": { "token": "fldcnXXXXXX", "url": "https://xxx.feishu.cn/drive/folder/fldcnXXXXXX", "name": "文件夹名称" } }
注意事项:
folder_token 为父文件夹 token,可以通过 URL 获取或通过 API 查询接口说明: 获取指定文件夹下的文件和子文件夹列表
推荐方法 (Explorer v2):
GET /open-apis/drive/explorer/v2/folder/:folder_token/children响应示例:
json{ "code": 0, "data": { "children": { "file_token1": { "token": "file_token1", "name": "文件名", "type": "file" }, "folder_token1": { "token": "folder_token1", "name": "文件夹名", "type": "folder" } }, "parentToken": "folder_token" }, "msg": "success" }
注意事项:
type 为 folder 表示文件夹,为 file 表示文件children 是字典格式,不是数组接口说明: 上传文件到指定文件夹
POST /open-apis/drive/v1/files/upload_all
Content-Type: multipart/form-data请求参数: | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | file | binary | 是 | 文件二进制内容 | | file_name | string | 是 | 文件名 | | parent_type | string | 是 | 父节点类型,explorer = 云空间 | | parent_node | string | 是 | 父节点 token(文件夹 token) | | size | number | 是 | 文件大小(字节) |
响应示例:
json{ "code": 0, "data": { "file_token": "file_token" } }
注意事项:
parent_type 使用 explorer 表示云空间文件夹size 参数必填,建议在上传前计算文件大小接口说明: 根据文件 token 下载文件
GET /open-apis/drive/v1/files/:file_token/download请求参数: | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | file_token | string | 是 | 文件 token |
响应:
注意事项:
Authorization: Bearer {tenant_access_token}接口说明: 通过邮箱或手机号获取用户的 open_id
POST /open-apis/contact/v3/users/batch_get_id请求参数:
json{ "emails": ["user@example.com"], "mobiles": ["13800138000"], "include_resigned": false }
响应示例:
json{ "code": 0, "data": { "user_list": [ { "user_id": "ou_xxxxxxxxx", "email": "user@example.com", "status": { "is_activated": true, "is_resigned": false } } ] } }
注意事项:
contact:user.id:readonly 权限user_id 就是 open_id接口说明: 为文件夹添加用户权限
POST /open-apis/drive/v1/permissions/:token/members?type=folder请求参数:
json{ "member_type": "openid", "member_id": "ou_xxxxxxxxx", "perm": "full_access", "perm_type": "container", "type": "user" }
权限类型: | perm | 说明 | |------|------| | view | 可阅读 | | edit | 可编辑 | | full_access | 可管理(完全访问) |
注意事项:
member_id 必须是 open_id,不能是 user_id接口说明: 获取文件的详细信息
GET /open-apis/drive/v1/files/:file_token请求参数: | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | file_token | string | 是 | 文件或文件夹 token |
响应示例:
json{ "code": 0, "data": { "token": "token", "name": "名称", "type": "file/folder", "size": 1024, "created_time": 1234567890, "owner": { "open_id": "xxx" } } }
接口说明: 删除指定文件夹(删除后进入回收站)
DELETE /open-apis/drive/v1/files/:folder_token?type=folder请求参数: | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | folder_token | string | 是 | 文件夹 token | | type | string | 是 | 固定值 folder |
响应示例:
json{ "code": 0, "msg": "success" }
注意事项:
Python 示例:
python# 删除文件夹(带确认提示) def delete_folder_with_confirm(client, folder_token, folder_name, confirmed=False): # 1. 显示文件夹信息 print(f"即将删除文件夹: {folder_name}") print(f"Token: {folder_token}") # 2. 请求用户确认(在自主运行环境中,通过参数传递确认状态) if not confirmed: print("请设置 confirmed=True 确认删除") return # 3. 执行删除 result = client.delete_folder(folder_token) if result.get("code") == 0: print("删除成功!文件夹已进入回收站") else: print(f"删除失败: {result.get('msg')}") # 使用示例 - 必须显式确认 delete_folder_with_confirm(client, "folder_token", "测试文件夹", confirmed=True)
接口说明: 删除指定文件(删除后进入回收站)
DELETE /open-apis/drive/v1/files/:file_token?type=file请求参数: | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | file_token | string | 是 | 文件 token | | type | string | 是 | 固定值 file |
注意事项:
接口说明: 将文件或文件夹移动到指定文件夹
POST /open-apis/drive/v1/files/:file_token/move请求参数:
json{ "type": "file", "destination_folder_token": "目标文件夹token" }
类型说明: | type 值 | 说明 | |---------|------| | file | 普通文件 | | folder | 文件夹 | | doc | 文档 | | sheet | 电子表格 | | bitable | 多维表格 | | docx | 新版文档 |
接口说明: 复制文件到指定文件夹(异步操作)
POST /open-apis/drive/v1/files/:file_token/copy请求参数:
json{ "type": "file", "destination_folder_token": "目标文件夹token", "name": "复制后的新名称(可选)" }
响应示例:
json{ "code": 0, "data": { "ticket": "task_ticket_xxx" }, "msg": "success" }
注意事项:
check_task_status(ticket) 查询复制进度接口说明: 批量获取多个文件的元数据信息
POST /open-apis/drive/v1/metas/batch_query请求参数:
json{ "file_tokens": ["token1", "token2", "token3"] }
限制: 最多 100 个文件 token
接口说明: 获取文件的阅读、点赞、评论等统计信息
POST /open-apis/drive/v1/files/:file_token/statistics响应示例:
json{ "code": 0, "data": { "uv": 100, "pv": 200, "like_count": 10, "comment_count": 5 } }
接口说明: 获取谁访问了该文件的记录
POST /open-apis/drive/v1/files/:file_token/view_records请求参数:
json{ "page_size": 50, "page_token": "可选的分页token" }
接口说明: 在指定文件夹创建文件的快捷方式
POST /open-apis/drive/v1/files/create_shortcut请求参数:
json{ "file_token": "源文件token", "folder_token": "目标文件夹token", "type": "file" }
接口说明: 在云空间中搜索文件
POST /open-apis/suite/docs-api/search/object请求参数:
json{ "search_key": "title", "search_value": "搜索关键词", "page_size": 50 }
search_key 说明: | 值 | 说明 | |----|------| | title | 按标题搜索 | | content | 按内容搜索 |
注意事项:
user_access_token,不支持 tenant_access_token接口说明: 查询复制、移动等异步操作的任务状态
GET /open-apis/drive/v1/files/task_check?ticket=xxx请求参数: | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | ticket | string | 是 | 异步任务 ticket |
响应示例:
json{ "code": 0, "data": { "status": "success", "file_token": "新文件token" } }
status 说明: | 值 | 说明 | |----|------| | pending | 等待中 | | processing | 处理中 | | success | 成功 | | failed | 失败 |
| 错误码 | 含义 | 解决方案 | |--------|------|----------| | 0 | 成功 | — | | 99991663 | token 过期 | 重新获取 tenant_access_token | | 1061002 | 无权限 | 检查应用权限和文件夹授权 | | 1061001 | 文件/文件夹不存在 | 检查 token 是否正确 | | 1061045 | 文件大小超限 | 使用分片上传或减小文件大小 | | 404 | 文件不存在 | 常见原因:使用了字典 key 而非 item'token'],参见下方常见错误 |
在获取文件夹内容后尝试下载文件时,出现 404 错误。
混淆了飞书 API 返回数据结构中的两种"token":
json{ "children": { "nodcn5OkQG6q8Y4SuSncukJmCtc": { // ← 错误:这是字典的 key,不是下载用 token "token": "KdLTbke3BoN85RxQg5qcswFYnah", // ← 正确:这才是下载用的 token "name": "Screenshot_20260323-115306.png", "type": "file" } } }
pythonresult = client.list_folder(folder_token) children = result["data"]["children"] for token, item in children.items(): # ← token 实际是 dict_key (nodcn...) file_token = token # ← 错误!这会导致 404 client.download_file(file_token, "/path/to/file")
pythonresult = client.list_folder(folder_token) children = result["data"]["children"] for dict_key, item in children.items(): # dict_key 是 nodcn... file_token = item["token"] # ← 正确!从 item 中获取 token client.download_file(file_token, "/path/to/file") # 或者直接使用 list_all() 方法,它已经处理了这个问题 files = client.list_all(folder_token) for file in files: client.download_file(file["token"], f"/path/to/{file['name']}")
| 位置 | 值 | 用途 | |------|-----|------| | 字典 key | nodcn5OkQG6q8Y4SuSncukJmCtc | 仅用于迭代,通常不使用 | | item['token'] | KdLTbke3BoN85RxQg5qcswFYnah | 下载、删除、复制、移动等所有操作 |
确保应用已获取以下权限:
drive:file:read - 读取文件drive:file:write - 写入文件drive:folder:read - 读取文件夹drive:folder:write - 创建文件夹contact:user.id:readonly - 获取用户 ID(用于权限管理)get_file_info 测试 token 是否可用Other measured skills in the registry, with their headline benchmark lift.