最近做的企微二开,机器人要能处理文件——客户发来订单 Excel,机器人解析后回一份汇总报告;销售让机器人发产品资料 PDF 给客户。和之前聊的文件自动处理不同,那篇重点是接收客户文件做业务解析,这篇重点是机器人自己上传、解析、发送文件的完整闭环——机器人怎么调 CDN 接口上传文件、怎么解析文件内容、怎么把文件发给客户。把调了哪些接口记下来。

 Eyun 平台开放的企微 API,统一 POST+JSON,鉴权用 App Token 加 appid(Authorization: Bearer eyk_xxxx),路径 {BASE_URL}/wx-api/api/<模块>/<动作>,响应封套 {code, data, detail, message, time},code 为 0 成功。

文件上传:调 CDN 接口

机器人生成文件后(比如解析完 Excel 生成汇总报告),要上传到 CDN 拿 fileId,再用 fileId 发送。上传调 CDN 模块:

import requests

BASE = "https://api.eyun.com"
HEADERS = {"Authorization": "Bearer eyk_xxxx", "Content-Type": "application/json"}

def upload_file(appid, file_path, file_name):
    with open(file_path, "rb") as f:
        resp = requests.post(
            f"{BASE}/wx-api/api/cdn/upload",
            headers={"Authorization": HEADERS["Authorization"]},  # 上传不带Content-Type
            files={"file": (file_name, f)},
            data={"appid": appid}
        )
    body = resp.json()
    if body["code"] == 0:
        return body["data"]["fileId"]  # 拿到fileId用于发送
    raise Exception(body["message"])

上传是 multipart/form-data,不是 JSON,所以 Content-Type 要去掉,让 requests 自动设。返回的 fileId 是文件在 CDN 的唯一标识,后续发送文件用。

文件下载:调 CDN 接口

客户发来文件,机器人要下载解析。下载调 CDN 模块:

def download_file(appid, file_id, save_path):
    resp = requests.post(
        f"{BASE}/wx-api/api/cdn/download",
        headers=HEADERS,
        json={"appid": appid, "fileId": file_id},
        stream=True
    )
    if resp.json().get("code") == 0:
        with open(save_path, "wb") as f:
            for chunk in resp.iter_content(8192):
                f.write(chunk)
        return save_path
    raise Exception(resp.json()["message"])

下载是流式的,大文件不会爆内存。fileId 从客户发文件消息的回调里拿。下载完存本地或 OSS,解析完删本地文件。

文件解析:按类型处理

下载完按扩展名识别类型,分别解析:

import openpyxl
import PyPDF2

def parse_file(file_path, file_name):
    ext = file_name.rsplit(".", 1)[-1].lower()
    
    if ext in ["xlsx", "xls"]:
        return parse_excel(file_path)
    elif ext == "pdf":
        return parse_pdf(file_path)
    elif ext == "csv":
        return parse_csv(file_path)
    else:
        return {"type": "unknown", "content": ""}

def parse_excel(file_path):
    wb = openpyxl.load_workbook(file_path)
    ws = wb.active
    headers = [c.value for c in ws[1]]
    rows = []
    for row in ws.iter_rows(min_row=2, values_only=True):
        rows.append(dict(zip(headers, row)))
    return {"type": "excel", "headers": headers, "rows": rows}

解析返回结构化数据,机器人基于数据生成回复或报告。表头别名匹配(订单号/订单编号)适应不同客户格式。

发送文件:调消息接口

机器人解析完生成报告文件,上传 CDN 拿 fileId 后,调消息接口发文件给客户:

def send_file(appid, to_uin, file_id, file_name):
    resp = requests.post(
        f"{BASE}/wx-api/api/message/sendFile",
        headers=HEADERS,
        json={
            "appid": appid,
            "to": to_uin,
            "fileId": file_id,
            "fileName": file_name
        }
    )
    return resp.json()["code"] == 0

fileId 是上传时拿到的,fileName 是客户看到的文件名。发送文件接口和发送文本接口走不同路径——sendFile 而不是 sendText。

完整闭环:接收→解析→生成→发送

客户发 Excel,机器人解析后生成汇总报告发回去,完整流程:

def handle_file_and_reply(appid, from_uin, file_id, file_name):
    # 1. 下载文件
    local_path = f"/tmp/{file_id}_{file_name}"
    download_file(appid, file_id, local_path)
    
    # 2. 解析文件
    parsed = parse_file(local_path, file_name)
    
    if parsed["type"] == "excel":
        # 3. 生成汇总报告
        report_path = generate_report(parsed["rows"])
        report_name = f"汇总报告_{file_name}"
        
        # 4. 上传报告到CDN
        report_file_id = upload_file(appid, report_path, report_name)
        
        # 5. 发送报告文件给客户
        send_file(appid, from_uin, report_file_id, report_name)
        
        # 6. 发文字说明
        requests.post(
            f"{BASE}/wx-api/api/message/sendText",
            headers=HEADERS,
            json={"appid": appid, "to": from_uin,
                  "content": f"已解析 {len(parsed['rows'])} 条数据,汇总报告见文件"}
        )
    
    # 清理本地文件
    import os
    os.remove(local_path)
    if 'report_path' in locals():
        os.remove(report_path)

整个闭环涉及五个接口调用:cdn/download 下载、解析(本地)、cdn/upload 上传、message/sendFile 发文件、message/sendText 发文字说明。关于文件处理相关接口,在Eyun 企业微信 API 平台有完整说明。

文件处理的几个坑

  • 上传是 multipart,不是 JSON,Content-Type 不能带

  • fileId 有有效期(几天),过期的要重新上传

  • 大文件上传超时要设长(timeout=120)

  • 解析 Excel 大文件要分批读,不然内存爆

  • 发送文件后客户可能看不到预览(企微客户端限制),要配文字说明

写在最后

机器人文件处理这套东西,本质是把企微的 CDN 接口和消息接口串起来——cdn/download 下载客户文件、本地解析、cdn/upload 上传处理结果、message/sendFile 发文件给客户。把上传下载做对、解析做扎实、闭环跑通,机器人真正能处理文件——而不是只会发文字的半成品。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐