钉钉机器人发送的群聊文件(常规如excel、pdf等)无法预览

阿里云服务器

钉钉机器人发送的文件(Excel、PDF 等)在群聊中无法预览,通常是因为发送方式文件来源不符合钉钉的预览机制。钉钉的预览功能依赖于文件被上传到钉钉的云端存储(MediaId),而不是仅仅发送一个网络链接。

以下是导致该问题的核心原因及解决方案:

❌ 核心原因分析

  1. 发送的是“链接”而非“文件”

    • 现象:机器人发送的消息是一个蓝色的超链接(如 http://.../file.xlsx),点击后跳转浏览器下载,而不是在聊天窗口直接显示“预览”按钮。

    • 原因:大多数机器人代码是通过 Link 消息类型发送的,只传递了 URL。钉钉无法预知外部链接的内容格式,因此不提供内置预览。

    • 解决:必须使用 “文件消息” (File Message) 接口,先将文件二进制流上传到钉钉服务器获取 media_id,再发送。

  2. 文件格式不支持或损坏

    • 文件扩展名与实际内容不符(例如把 .txt 改名为 .pdf)。

    • 文件加密或受密码保护(钉钉无法预览加密文档)。

    • 文件版本过高(如某些特殊的 Excel 宏文件 .xlsm 可能支持不佳,建议用 .xlsx)。

    • 现象:显示了文件卡片,但点击预览报错或白屏。

    • 原因

  3. 使用了错误的消息类型

    • 使用了 MarkdownText 消息类型来包裹文件链接,这永远无法触发预览。


✅ 解决方案:如何发送可预览的文件

要让文件在钉钉群内直接预览,必须遵循 “先上传,后发送” 的两步流程。

步骤 1:调用“上传临时素材”接口

先将本地文件上传到钉钉服务器,换取一个 media_id。该 ID 有效期通常为 3 天。

  • 接口地址POST https://oapi.dingtalk.com/media/upload

  • 参数

    • access_token: 机器人的访问令牌。

    • type: 固定填 file

    • media: 文件的二进制流 (multipart/form-data)。

Python 示例代码:

import requests

def upload_file_to_dingtalk(access_token, file_path):
    url = f"https://oapi.dingtalk.com/media/upload?access_token={access_token}&type=file"
    
    files = {
        'media': open(file_path, 'rb')
    }
    
    response = requests.post(url, files=files)
    result = response.json()
    
    if result.get('errcode') == 0:
        return result['media_id']
    else:
        raise Exception(f"上传失败: {result}")

步骤 2:调用“发送文件消息”接口

使用上一步拿到的 media_id 发送消息。

  • 接口地址POST https://oapi.dingtalk.com/robot/send (群机器人) 或 /v1.0/im/agents/messages/send (新版)

  • 消息类型file

  • 关键参数

    • media_id: 步骤 1 获取的 ID。

    • fileName: 显示的文件名(必须带后缀,如 report.xlsx)。

    • fileSize: 文件大小(字节)。

Python 示例代码:

def send_file_message(webhook, media_id, file_name, file_size):
    headers = {'Content-Type': 'application/json'}
    
    data = {
        "msgtype": "file",
        "file": {
            "media_id": media_id,
            "fileName": file_name,
            "fileSize": file_size
        }
    }
    
    # 注意:如果是群机器人 webhook,不需要 access_token 在 URL 里,直接在 body 发
    # 如果是企业内部 Agent,则用 /v1.0/im/agents/messages/send 接口
    response = requests.post(webhook, json=data, headers=headers)
    print(response.text)

💡 特殊情况处理

1. 文件在 OSS/外部链接,不想下载再上传?

如果文件已经在阿里云 OSS 上,你想避免“下载到本地再上传到钉钉”的流量浪费:

  • 方案:在服务器内存中流转。

    • 使用代码从 OSS 读取流 (stream) -> 直接 requests.post 给钉钉上传接口。

    • 不需要保存到本地磁盘,节省 IO 和空间。

2. 超大文件 (>20MB)

钉钉机器人对单个文件大小有限制(通常群机器人限制 20MB,企业内部应用可能稍大)。

  • 超过限制:无法通过 file 消息发送。

  • 替代方案:只能发送 Link 消息,引导用户去浏览器下载。此时无法预览是正常机制,无法绕过。

3. 新版接口 (Work Notice)

如果你使用的是钉钉新版开发平台(H5 微应用/企业内部应用),请使用 /v1.0/im/agents/messages/send 接口,逻辑一样,也是先上传媒体库获取 mediaId,再发送 msgKey: "sampleFile" (或对应 file 类型)。

🚀 快速自查清单

检查项正确做法错误做法
消息类型msgtype: "file"msgtype: "link""markdown"
文件来源已上传至钉钉,拥有 media_id直接发送 http/https 外链
文件名包含正确后缀 (.pdf, .xlsx)无后缀或后缀错误
文件大小< 20MB (群机器人)> 20MB
文件内容未加密、标准格式加密、损坏、特殊宏

总结

钉钉不支持对外部链接直接预览。
要实现预览,必须通过 API 将文件二进制流上传到钉钉服务器获取 media_id,然后以 file 消息类型发送。这是唯一能触发钉钉内置文档预览组件的方法。