程序员花2小时踩坑OpenClaw飞书上传,总结5个经验,建议收藏
今天在用OpenClaw开发飞书自动化时,遇到一个超级坑的问题:文件上传死活不成功。
本来以为10分钟能搞定,结果花了我整整2个小时!
试了无数种方法,翻了N遍文档,最后终于解决了。
把整个过程整理出来,希望能帮正在用OpenClaw的你避坑。
如果你也在用OpenClaw或飞书API,这篇文章可能会帮你节省2小时。
需求很简单
我想让OpenClaw自动生成PDF报告,然后通过飞书发送到群聊。
步骤:
- Python生成PDF ✅
- 上传到飞书 ❌(卡住了)
- 发送消息到群聊
第一个坑:I/O错误
我的代码看起来没问题:
with open(file_path, "rb") as f: body = CreateFileRequestBody.builder() \ .file_type("pdf") \ .file(f.read()) # 读取文件内容 .build()结果报错:
I/O operation on closed file什么鬼?明明在with块里,怎么会文件关闭?
我当时就懵了...
试了3种方法才找到原因
方法1:不用with语句
f = open(file_path, "rb")body = CreateFileRequestBody.builder().file(f.read()).build()f.close()结果:还是报错 ❌
方法2:检查文件权限
以为文件权限有问题,各种chmod...
结果:还是不行 ❌
方法3:直接传文件对象 ✅
with open(file_path, "rb") as f: body = CreateFileRequestBody.builder() \ .file(f) # 不read,直接传文件对象 .build()结果:成功了!
原因分析:
- SDK内部会自己读取文件
- 传f.read(),文件就关了
- SDK再去读已关闭的文件,就报错
又踩新坑:file_type参数
以为解决了,结果又来一个...
用了.file(f)后,上传是成功了,但飞书无法预览PDF!
我试了:
- file_type="pdf" ❌
- file_type="doc" ❌
- file_type="stream" ✅
最终方案:
with open(file_path, "rb") as f: body = CreateFileRequestBody.builder() \ .file_type("stream") \ .file_name("report.pdf") \ .file(f) \ .build()完美解决!

关键点:
- file_type="stream" 适用于所有文件
- 比指定具体类型更可靠
- 官方文档没说清楚!
还有3个坑
坑3:字段验证失败
解决上传后,发送消息又报错:
code: 99992402msg: field validation failed问题代码:
# ❌ 错误写法msg_body = CreateMessageRequestBody.builder() \ .receive_id_type("open_id") # 位置错了 .build()正确写法:
# ✅ 正确写法msg_body = CreateMessageRequestBody.builder() \ .receive_id(chat_id) \ .build()msg_req = CreateMessageRequest.builder() \ .receive_id_type("open_id") # 要在这里设置! .request_body(msg_body) \ .build()原因:receive_id_type 必须在请求级别设置,不能在body里。
坑4:文档写入失败
用OpenClaw的feishu_doc工具写文档,写入成功但打开是空白页面!
解决:
- 刷新飞书页面
- 或重新打开文档
- 数据其实写入了,只是缓存问题
坑5:本地路径无法访问
直接发服务器路径(如/tmp/file.pdf),收件人无法访问!
解决:
- 必须先用API上传文件
- 获取file_key
- 再用file_key发送消息
最终代码
经过2小时踩坑,最终的正确方案:
from lark_oapi import Clientfrom lark_oapi.api.im.v1 import *import json# 配置client = Client.builder() \ .app_id(app_id) \ .app_secret(app_secret) \ .build()# 上传文件with open(file_path, "rb") as f: body = CreateFileRequestBody.builder() \ .file_type("stream") \ .file_name(filename) \ .file(f) \ .build() resp = client.im.v1.file.create( CreateFileRequest.builder().request_body(body).build() ) file_key = resp.data.file_key# 发送消息content = json.dumps({"file_key": file_key})msg_body = CreateMessageRequestBody.builder() \ .receive_id(chat_id) \ .msg_type("file") \ .content(content) \ .build()msg_req = CreateMessageRequest.builder() \ .receive_id_type("open_id") \ .request_body(msg_body) \ .build()client.im.v1.message.create(msg_req)3个关键点:
- ✅ file_type="stream"
- ✅ .file(f) 不要.file(f.read())
- ✅ receive_id_type在请求级别
5个坑总结
坑 | 错误做法 | 正确做法 |
文件读取 | .file(f.read()) | .file(f) |
文件类型 | file_type="pdf" | file_type="stream" |
参数位置 | body里设置receive_id_type | 请求级别设置 |
文档缓存 | 写完立即看 | 刷新页面 |
路径问题 | 发本地路径 | 先上传获file_key |
避坑建议
给OpenClaw开发者:
- ✅ 先用Python测试API
- ✅ 确认无误再集成OpenClaw
- ✅ 仔细看SDK文档
- ✅ 遇到问题别慌,耐心排查
给飞书API使用者:
- ✅ file_type用stream最稳
- ✅ 注意参数设置位置
- ✅ 文件上传两步走:上传→发送
你遇到过类似的问题吗?
- 你在用OpenClaw还是飞书API?
- 有没有踩过其他坑?
- 有什么更好的解决方案?
欢迎在评论区分享你的经验!
如果这篇文章帮到了你,点赞、收藏、转发给更多人看到~
标签:OpenClaw、飞书、API开发、Python、程序员、踩坑经验、技术分享、文件上传、自动化