feishu file transfer guide

# OpenClaw 飞书文件传输技术分享

Safety Notice

This listing is from the official public ClawHub registry. Review SKILL.md and referenced scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "feishu file transfer guide" with this command: npx skills add swingmonkey/feishu-file-transfer-guide

OpenClaw 飞书文件传输技术分享

作者: SwingMonkey

日期: 2026-03-14

适用: OpenClaw Agent 飞书文件传输场景


一、问题背景

OpenClaw 的 message 工具在飞书渠道发送本地文件时,会直接发送文件路径而非上传文件内容。需要通过飞书 API 实现真正的文件上传和发送。


二、核心流程

┌─────────────┐     ┌─────────────┐     ┌─────────────┐
│  获取 Token  │ ──▶ │  上传文件   │ ──▶ │  发送消息   │
│  (Step 1)   │     │  (Step 2)   │     │  (Step 3)   │
└─────────────┘     └─────────────┘     └─────────────┘
       │                   │                   │
       ▼                   ▼                   ▼
   tenant_            file_key            消息送达
   access_token       (文件标识)          飞书用户

三、详细步骤

Step 1: 获取 tenant_access_token

接口: POST https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal

请求头:

Content-Type: application/json

请求体:

{
  "app_id": "cli_xxxxxxxxxx",
  "app_secret": "xxxxxxxxxx"
}

PowerShell 实现:

$tokenResponse = Invoke-RestMethod `
    -Uri 'https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal' `
    -Method POST `
    -Headers @{'Content-Type'='application/json'} `
    -Body '{"app_id":"cli_xxxxxxxxxx","app_secret":"xxxxxxxxxx"}'

$TOKEN = $tokenResponse.tenant_access_token

返回示例:

{
  "code": 0,
  "msg": "ok",
  "tenant_access_token": "t-xxxxxxxxxx",
  "expire": 7200
}

Step 2: 上传文件获取 file_key

接口: POST https://open.feishu.cn/open-apis/im/v1/files

关键要点:

  • 使用 multipart/form-data 格式
  • 文件名使用英文(避免中文编码问题)
  • 必须包含 filefile_type 字段

Python 实现(推荐):

import urllib.request
import json
import ssl

# SSL 配置
ssl_context = ssl.create_default_context()
ssl_context.check_hostname = False
ssl_context.verify_mode = ssl.CERT_NONE

def upload_file(token, file_path, display_name):
    """
    上传文件到飞书
    
    Args:
        token: tenant_access_token
        file_path: 本地文件路径
        display_name: 显示文件名(建议英文)
    
    Returns:
        file_key: 文件标识
    """
    url = 'https://open.feishu.cn/open-apis/im/v1/files'
    
    # 读取文件
    with open(file_path, 'rb') as f:
        file_data = f.read()
    
    # 构建 multipart
    boundary = '----WebKitFormBoundary7MA4YWxkTrZu0gW'
    body = b''
    
    # file 字段
    body += f'------{boundary}\r\n'.encode('utf-8')
    body += f'Content-Disposition: form-data; name="file"; filename="{display_name}"\r\n'.encode('utf-8')
    body += b'Content-Type: application/octet-stream\r\n\r\n'
    body += file_data
    body += b'\r\n'
    
    # file_type 字段
    body += f'------{boundary}\r\n'.encode('utf-8')
    body += b'Content-Disposition: form-data; name="file_type"\r\n\r\n'
    body += b'stream\r\n'
    
    # 结束
    body += f'------{boundary}--\r\n'.encode('utf-8')
    
    # 请求
    req = urllib.request.Request(url, data=body, method='POST')
    req.add_header('Authorization', f'Bearer {token}')
    req.add_header('Content-Type', f'multipart/form-data; boundary=----{boundary}')
    
    with urllib.request.urlopen(req, context=ssl_context) as response:
        result = json.loads(response.read().decode('utf-8'))
        return result['data']['file_key']

# 使用示例(支持中文文件名)
FILE_KEY = upload_file(
    token='t-xxxxxxxxxx',
    file_path='/path/to/your/file.docx',
    display_name='语文.docx'  # 支持中文文件名
)

返回示例:

{
  "code": 0,
  "data": {
    "file_key": "file_v3_00vp_xxxxxxxxxx"
  },
  "msg": "success"
}

Step 3: 发送文件消息

接口: POST https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=open_id

请求头:

Authorization: Bearer {tenant_access_token}
Content-Type: application/json; charset=utf-8

请求体:

{
  "receive_id": "ou_xxxxxxxxxx",
  "msg_type": "file",
  "content": "{\"file_key\":\"file_v3_00vp_xxxxxxxxxx\"}"
}

PowerShell 实现:

$body = @{
    receive_id = "ou_xxxxxxxxxx"
    msg_type = "file"
    content = '{"file_key":"file_v3_00vp_xxxxxxxxxx"}'
} | ConvertTo-Json

Invoke-RestMethod `
    -Uri 'https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=open_id' `
    -Method POST `
    -Headers @{
        'Authorization' = "Bearer $TOKEN"
        'Content-Type' = 'application/json; charset=utf-8'
    } `
    -Body $body

返回示例:

{
  "code": 0,
  "data": {
    "message_id": "om_xxxxxxxxxx",
    "msg_type": "file"
  },
  "msg": "success"
}

四、完整示例代码

Python 完整版

#!/usr/bin/env python3
"""
OpenClaw 飞书文件传输工具
用法: python feishu_transfer.py <file_path> <receive_id>
"""

import urllib.request
import json
import ssl
import os
import sys

class FeishuFileTransfer:
    def __init__(self, app_id, app_secret):
        self.app_id = app_id
        self.app_secret = app_secret
        self.ssl_context = ssl.create_default_context()
        self.ssl_context.check_hostname = False
        self.ssl_context.verify_mode = ssl.CERT_NONE
    
    def get_token(self):
        """获取 tenant_access_token"""
        url = 'https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal'
        data = {'app_id': self.app_id, 'app_secret': self.app_secret}
        
        req = urllib.request.Request(
            url, 
            data=json.dumps(data).encode('utf-8'), 
            method='POST'
        )
        req.add_header('Content-Type', 'application/json')
        
        with urllib.request.urlopen(req, context=self.ssl_context) as res:
            result = json.loads(res.read().decode('utf-8'))
            return result['tenant_access_token']
    
    def upload_file(self, token, file_path, display_name=None):
        """上传文件"""
        if display_name is None:
            display_name = os.path.basename(file_path)
        
        url = 'https://open.feishu.cn/open-apis/im/v1/files'
        
        with open(file_path, 'rb') as f:
            file_data = f.read()
        
        # 构建 multipart
        boundary = '----WebKitFormBoundary7MA4YWxkTrZu0gW'
        body = b''
        body += f'------{boundary}\r\n'.encode('utf-8')
        body += f'Content-Disposition: form-data; name="file"; filename="{display_name}"\r\n'.encode('utf-8')
        body += b'Content-Type: application/octet-stream\r\n\r\n'
        body += file_data
        body += b'\r\n'
        body += f'------{boundary}\r\n'.encode('utf-8')
        body += b'Content-Disposition: form-data; name="file_type"\r\n\r\n'
        body += b'stream\r\n'
        body += f'------{boundary}--\r\n'.encode('utf-8')
        
        req = urllib.request.Request(url, data=body, method='POST')
        req.add_header('Authorization', f'Bearer {token}')
        req.add_header('Content-Type', f'multipart/form-data; boundary=----{boundary}')
        
        with urllib.request.urlopen(req, context=self.ssl_context) as res:
            result = json.loads(res.read().decode('utf-8'))
            return result['data']['file_key']
    
    def send_file(self, token, file_key, receive_id):
        """发送文件消息"""
        url = 'https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=open_id'
        data = {
            'receive_id': receive_id,
            'msg_type': 'file',
            'content': json.dumps({'file_key': file_key})
        }
        
        req = urllib.request.Request(
            url, 
            data=json.dumps(data).encode('utf-8'), 
            method='POST'
        )
        req.add_header('Authorization', f'Bearer {token}')
        req.add_header('Content-Type', 'application/json')
        
        with urllib.request.urlopen(req, context=self.ssl_context) as res:
            return json.loads(res.read().decode('utf-8'))

# 使用示例
if __name__ == '__main__':
    # 配置(替换为你的凭证)
    APP_ID = 'cli_xxxxxxxxxx'
    APP_SECRET = 'xxxxxxxxxx'
    FILE_PATH = '/path/to/your/file.docx'
    RECEIVE_ID = 'ou_xxxxxxxxxx'
    
    # 执行传输(支持中文文件名)
    transfer = FeishuFileTransfer(APP_ID, APP_SECRET)
    token = transfer.get_token()
    file_key = transfer.upload_file(token, FILE_PATH, '语文.docx')  # 中文文件名
    result = transfer.send_file(token, file_key, RECEIVE_ID)
    
    print(f'发送成功: {result}')

五、关键注意事项

1. 文件名编码问题

  • 问题: 早期中文文件名可能显示为乱码
  • 解决: 确保 multipart 请求中 file_name 字段正确编码为 UTF-8
  • 验证: 中文文件名 语文.docx 可以正常显示

2. 文件大小限制

  • 问题: 不能上传空文件(大小为 0 字节)
  • 解决: 确保文件有实际内容

3. 编码设置

  • PowerShell: 使用 -ContentType 'application/json; charset=utf-8'
  • Python: 使用 encode('utf-8') 处理中文

4. 避免重复发送

  • 确认上传成功后再执行发送步骤
  • 不要多次调用发送 API

六、常见问题排查

问题原因解决
文件名显示为乱码编码问题确保 file_name 字段 UTF-8 编码
上传返回 400文件为空确保文件有内容
发送后文件名是 UUID未正确设置文件名在上传时指定 filename
中文内容乱码编码问题使用 charset=utf-8

七、参考文档


本文档由 SwingMonkey 整理分享,供社区参考使用

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

Leads

Leads - command-line tool for everyday use

Registry SourceRecently Updated
General

Bmi Calculator

BMI计算器。BMI计算、理想体重、健康计划、体重追踪、儿童BMI、结果解读。BMI calculator with ideal weight, health plan. BMI、体重、健康。

Registry SourceRecently Updated
General

Blood

Blood — a fast health & wellness tool. Log anything, find it later, export when needed.

Registry SourceRecently Updated
General

Better Genshin Impact

📦BetterGI · 更好的原神 - 自动拾取 | 自动剧情 | 全自动钓鱼(AI) | 全自动七圣召唤 | 自动伐木 | 自动刷本 | 自动采集/挖矿/锄地 | 一条龙 | 全连音游 - UI A better genshin impact, c#, auto-play-game, automatic, g...

Registry SourceRecently Updated