Overview
This skill uploads files to Feishu (Lark) Bitable attachment fields through the material upload flow:
- 1. Get source file (local copy, URL download, or Feishu message download)
- Upload to Bitable upload endpoint with INLINECODE0
- Get
file_token from upload response - Create/Update record with attachment field
Key design: This is a general-purpose skill for ANY Bitable your app can access. Nothing is hardcoded.
Verification Status
Local Tests Passed
- - [x] All Python modules pass syntax check (py_compile)
- [x] All custom exception classes are properly imported
- [x] File not found raises
SkillFileNotFoundError (not NameError) - [x] Input validation raises
SkillInputError for missing parameters - [x] All payload example files are valid JSON
- [x]
main.py --help runs successfully
Requires Real Environment Verification
- - [ ] Bitable record update/create response format
- [ ] Table/field listing API response structure
- [ ] Record search API filter syntax
If any API calls fail in your environment, check references/feishu-api-notes.md for extensibility points.
Supported Source Types
| Type | Description | Example |
|---|
| INLINECODE6 | Local file path | INLINECODE7 |
| INLINECODE8 |
Download from HTTP(S) URL |
{"type": "url", "ref": "https://example.com/file.pdf"} |
|
feishu_message | Feishu message attachment |
{"type": "feishu_message", "ref": {"file_key": "file_xxx"}} |
Target Resolution
This skill supports flexible target specification to work with any Bitable:
Table Specification (priority: tableid > tablename)
- - Provide
table_id directly for fastest resolution - Or provide
table_name for automatic lookup (lists all tables and matches by name)
Field Specification (priority: fieldid > fieldname)
- - Provide
field_id directly for fastest resolution - Or provide
field_name for automatic lookup (lists all fields and matches by name)
Record Specification
- - Provide
record_id to update existing record - Or provide
lookup to search for record by field value - Or omit both to create new record
Input JSON Structure
CODEBLOCK0
Target Parameters
| Parameter | Required | Description |
|---|
| INLINECODE18 | Yes | Bitable app token (basc...) |
| INLINECODE19 |
No
| Table ID (tbl...). Required if table_name not provided |
|
table_name | No
| Table display name. Required if table_id not provided |
|
record_id | No | Record ID (rec...). Leave empty to create new record |
|
field_id | No
| Field ID. Required if field_name not provided |
|
field_name | No
| Field display name. Required if field_id not provided |
|
lookup | No | Config to find record_id by searching |
|
allow_create_if_lookup_missing | No | If true, create new record when lookup finds nothing |
Lookup Config
CODEBLOCK1
Source Parameters
| Parameter | Required | Description |
|---|
| INLINECODE26 | Yes | One of: local, url, INLINECODE29 |
| INLINECODE30 |
Yes | local: file path / url: download URL / feishu_message:
{file_key, filename} |
Append Mode
| Value | Behavior |
|---|
| INLINECODE32 | Read existing attachments, append new file to the list |
| INLINECODE33 |
Replace attachment field with new file only |
Upload Flow
Small Files (≤20MB)
Direct upload to material endpoint:
CODEBLOCK2
Large Files (>20MB)
Chunked upload in 5MB parts:
- 1.
POST /open-apis/drive/v1/chunked_upload/prepare → uploadid - INLINECODE35 (per part) → etag
- INLINECODE36 → filetoken
Environment Variables
Set these before running:
CODEBLOCK3
Usage Examples
Local file with known record_id
CODEBLOCK4
URL download with replace mode
CODEBLOCK5
Feishu message attachment
CODEBLOCK6
Auto-resolve table by name
CODEBLOCK7
Lookup record by field value
CODEBLOCK8
Create new record with attachment
CODEBLOCK9
Basic Verification
Run syntax check before use:
CODEBLOCK10
This verifies:
- - All Python modules have valid syntax
- No undefined variables or imports
Output
Success
CODEBLOCK11
Error
CODEBLOCK12
Common Errors
| Error Type | Cause | Solution |
|---|
| INLINECODE37 | Local file does not exist | Check file path |
| INLINECODE38 |
URL download failed | Verify URL accessibility |
|
input_error | Invalid parameters | Check input JSON structure |
|
auth_error | Invalid credentials | Check FEISHU
APPID/SECRET |
|
upload_error | Upload failed | Check app permissions |
|
resolve_error | Table/field/record not found | Verify names or IDs |
|
update_error | Record update failed | Check record exists |
Why This Skill Works with Any Bitable
This skill is not hardcoded to a specific Bitable:
- 1. Dynamic apptoken: Read from input, not hardcoded
- Dynamic table resolution: Supports tableid (direct) or tablename (API lookup)
- Dynamic field resolution: Supports fieldid (direct) or fieldname (API lookup)
- Dynamic record resolution: Supports recordid, lookup search, or create-new mode
References
See references/feishu-api-notes.md for:
- - Why filetoken from IM/Drive cannot be reused directly
- Why upload to bitablefile upload point is required
- API implementation notes and extensibility points
- Known uncertainties that may need environment-specific verification
概述
该技能通过素材上传流程将文件上传至飞书多维表格附件字段:
- 1. 获取源文件(本地副本、URL下载或飞书消息下载)
- 通过 parenttype=bitablefile 上传至多维表格上传端点
- 从上传响应中获取 file_token
- 创建/更新包含附件字段的记录
核心设计:这是一个适用于您的应用可访问的任何多维表格的通用技能,无任何硬编码内容。
验证状态
本地测试通过
- - [x] 所有Python模块通过语法检查(py_compile)
- [x] 所有自定义异常类已正确导入
- [x] 文件未找到时抛出 SkillFileNotFoundError(而非NameError)
- [x] 缺少参数时输入验证抛出 SkillInputError
- [x] 所有负载示例文件均为有效JSON
- [x] main.py --help 运行成功
需真实环境验证
- - [ ] 多维表格记录更新/创建响应格式
- [ ] 表格/字段列表API响应结构
- [ ] 记录搜索API筛选语法
若您的环境中任何API调用失败,请查看 references/feishu-api-notes.md 了解扩展点。
支持的源类型
| 类型 | 描述 | 示例 |
|---|
| local | 本地文件路径 | {type: local, ref: /tmp/file.pdf} |
| url |
从HTTP(S) URL下载 | {type: url, ref: https://example.com/file.pdf} |
| feishu
message | 飞书消息附件 | {type: feishumessage, ref: {file
key: filexxx}} |
目标解析
该技能支持灵活的目标指定,可适用于任何多维表格:
表格指定(优先级:tableid > tablename)
- - 直接提供 tableid 实现最快解析
- 或提供 tablename 实现自动查找(列出所有表格并按名称匹配)
字段指定(优先级:fieldid > fieldname)
- - 直接提供 fieldid 实现最快解析
- 或提供 fieldname 实现自动查找(列出所有字段并按名称匹配)
记录指定
- - 提供 record_id 更新现有记录
- 或提供 lookup 按字段值搜索记录
- 或两者均省略以创建新记录
输入JSON结构
json
{
target: {
app_token: bascxxxxxxxxxxxxx,
table_id: tblxxxxxxxxxx,
table_name: ,
record_id: recxxxxxxxxxx,
field_id: fldxxxxxxxxxx,
field_name: 附件,
lookup: {
field_name: 合同编号,
field_id: ,
value: HT-2026-001
},
allowcreateiflookupmissing: false
},
source: {
type: local,
ref: /path/to/file.pdf
},
append: true
}
目标参数
| 参数 | 必需 | 描述 |
|---|
| apptoken | 是 | 多维表格apptoken(basc...) |
| tableid |
否
| 表格ID(tbl...)。未提供tablename时必需 |
| table
name | 否 | 表格显示名称。未提供tableid时必需 |
| record_id | 否 | 记录ID(rec...)。留空则创建新记录 |
| field
id | 否 | 字段ID。未提供fieldname时必需 |
| field
name | 否 | 字段显示名称。未提供fieldid时必需 |
| lookup | 否 | 通过搜索查找record_id的配置 |
| allow
createif
lookupmissing | 否 | 若为true,查找无结果时创建新记录 |
查找配置
json
lookup: {
field_name: 合同编号,
field_id: ,
value: HT-2026-001
}
源参数
| 参数 | 必需 | 描述 |
|---|
| type | 是 | 可选值:local、url、feishumessage |
| ref |
是 | local:文件路径 / url:下载URL / feishumessage:{file_key, filename} |
追加模式
| 值 | 行为 |
|---|
| true | 读取现有附件,将新文件追加到列表中 |
| false |
仅用新文件替换附件字段 |
上传流程
小文件(≤20MB)
直接上传至素材端点:
POST /open-apis/drive/v1/upload
multipart/form-data 字段:
- file:<文件内容>
- file_name:文件名
- size:文件大小(字节)
- parenttype:bitablefile
- parentnode:{apptoken}
- extra:{driveroutetoken: {app_token}}
大文件(>20MB)
以5MB分片上传:
- 1. POST /open-apis/drive/v1/chunkedupload/prepare → uploadid
- POST /open-apis/drive/v1/chunkedupload(每分片)→ etag
- POST /open-apis/drive/v1/chunkedupload/finish → file_token
环境变量
运行前设置:
bash
export FEISHUAPPID=yourappid
export FEISHUAPPSECRET=yourappsecret
export FEISHUBASEURL=https://open.feishu.cn # 可选
使用示例
已知record_id的本地文件
bash
python scripts/main.py --input payload.local.json
URL下载替换模式
bash
python scripts/main.py --input payload.url.json
飞书消息附件
bash
python scripts/main.py --input payload.feishu_message.json
按名称自动解析表格
bash
python scripts/main.py --input payload.table_name.json
按字段值查找记录
bash
python scripts/main.py --input payload.lookup.json
创建带附件的新记录
bash
python scripts/main.py --input payload.create_record.json
基础验证
使用前运行语法检查:
bash
python -m py_compile scripts/*.py
此操作验证:
- - 所有Python模块语法有效
- 无未定义的变量或导入
输出
成功
json
{
ok: true,
file_token: vobxxxxxxxxxx,
app_token: bascxxxxxxxxxx,
table_id: tblxxxxxxxxxx,
table_name: 合同归档,
record_id: recxxxxxxxxxx,
field_name: 附件,
field_id: fldxxxxxxxxxx,
upload_type: direct,
attachment_count: 3,
mode: append,
message: Successfully uploaded report.pdf...
}
错误
json
{
ok: false,
error: Table xxx not found. Available tables: 表 1, 表 2,
error
type: resolveerror
}
常见错误
| 错误类型 | 原因 | 解决方案 |
|---|
| filenotfound | 本地文件不存在 | 检查文件路径 |
| download_failed |
URL下载失败 | 验证URL可访问性 |
| input_error | 参数无效 | 检查输入JSON结构 |
| auth
error | 凭据无效 | 检查FEISHUAPP_ID/SECRET |
| upload_error | 上传失败 | 检查应用权限 |
| resolve_error | 表格/字段/记录未找到 | 验证名称或ID |
| update_error | 记录更新失败 | 检查记录是否存在 |
为何该技能适用于任何多维表格
该技能未硬编码到特定多维表格:
- 1. 动态apptoken:从输入读取,非硬编码
- 动态表格解析:支持tableid(直接)或tablename(API查找)
- 动态字段解析:支持fieldid(直接)或fieldname(API查找)
- 动态记录解析:支持recordid、查找搜索或创建新模式
参考资料
参见 references/feishu-api-notes.md 了解:
- - 为何IM/Drive的filetoken不能直接复用
- 为何需要上传至bitablefile上传点
- API实现说明和扩展点