首页 / 博客 / API·多语言·接口

微信API发送图片、文件、视频、语音消息实战

分类:API·多语言·接口 · 标签:微信API、发图片、发文件

前言

在做微信机器人或自动化运营系统时,纯文本消息往往满足不了业务需求。图片通知、合同文件、语音播报、短视频推送——这些富媒体场景在客服机器人、内容分发、B端审批流中极为常见。然而,不少开发者在对接时会遇到几个共同困惑:图片怎么传、文件大小有没有限制、转发和上传有什么区别、批量发送时怎么防频控触发封号?

本文以 HTTP REST 接口为技术路径,覆盖图片、文件、视频、语音四类媒体消息的完整发送流程,包含 Python 示例代码、常见报错排查和批量发送的安全策略,帮助开发者快速打通多媒体消息能力。


一、媒体消息发送的整体架构

与纯文本消息不同,多媒体消息的发送通常有两种路径:

路径适用场景特点
直接上传路径本地文件首次发送携带文件内容上传,服务端返回 msgId
转发路径同一文件二次发送使用已有 msgId 转发,不重复上传流量

转发接口(forwardImage / forwardFile 等)本质上是"复用已上传的媒体资源",对批量场景非常友好:上传一次、转发 N 次,既省带宽又降低接口调用频率。

整体流程如下:

本地文件
   ↓
postImage / postFile / postVideo / postVoice(首次发送)
   ↓ 返回 msgId
forwardImage / forwardFile(转发给其他用户)

所有接口统一采用 HTTP POST + JSON body,鉴权 token 放在请求头,格式如下:

pythonBASE    = "https://你的接口域名"   # 注册后在官方文档获取
TOKEN   = "你的Token"
APPID   = "你的appId"              # 扫码登录后获得的设备ID
HEADERS = {"token": TOKEN}         # 鉴权字段名以官方文档为准
注:以下所有代码均为示例,具体接口路径、字段名称以官方文档为准。

二、发送图片消息

2.1 接口说明

发送图片使用 /message/postImage 接口,支持 URL 图片和 Base64 两种传入方式,推荐 URL 方式,传输更轻量。

pythonimport requests

def send_image(to_wxid: str, img_url: str) -> dict:
    """
    发送图片消息
    :param to_wxid: 接收方微信ID(个人wxid或群chatroom ID)
    :param img_url:  图片的公网可访问 URL
    """
    url = f"{BASE}/message/postImage"
    payload = {
        "appId": APPID,
        "toWxid": to_wxid,
        "imgUrl": img_url      # 字段名以官方文档为准
    }
    resp = requests.post(url, json=payload, headers=HEADERS, timeout=30)
    return resp.json()

result = send_image("wxid_xxxxxxxx", "https://cdn.example.com/banner.jpg")
if result.get("ret") == 200:
    print("图片发送成功,msgId:", result["data"]["msgId"])
else:
    print("发送失败:", result.get("msg"))

2.2 Base64 方式

当图片在本地、无法提供公网 URL 时,可转为 Base64 发送:

pythonimport base64

def send_image_b64(to_wxid: str, local_path: str) -> dict:
    with open(local_path, "rb") as f:
        b64_str = base64.b64encode(f.read()).decode()

    url = f"{BASE}/message/postImage"
    payload = {
        "appId": APPID,
        "toWxid": to_wxid,
        "imgBase64": b64_str   # 字段名以官方文档为准
    }
    return requests.post(url, json=payload, headers=HEADERS, timeout=30).json()

注意事项:Base64 编码会使数据体积增大约 33%,图片较大时建议先压缩再编码,避免请求体过大导致接口拒绝或超时。生产环境推荐将图片上传到 CDN,使用 URL 方式发送更为稳定。

2.3 转发已收到的图片

如果消息回调中接收到一张图片并需要转发给另一个用户,使用转发接口可以避免重新下载再上传:

pythondef forward_image(to_wxid: str, msg_id: str, from_wxid: str) -> dict:
    url = f"{BASE}/message/forwardImage"
    payload = {
        "appId": APPID,
        "toWxid": to_wxid,
        "msgId": msg_id,
        "fromWxid": from_wxid  # 原消息来源ID,字段以文档为准
    }
    return requests.post(url, json=payload, headers=HEADERS, timeout=30).json()

转发时需确保 msgIdfromWxid 的对应关系正确,否则会返回资源无效错误。若图片来自群聊,fromWxid 通常填群的 chatroom ID,具体以文档为准。


三、发送文件消息

3.1 接口说明

发送文件(PDF、Excel、Word、压缩包等)使用 /message/postFile 接口。与图片类似,支持 URL 和 Base64,此外还需传入文件名,否则接收端显示的文件名可能不正确。

pythondef send_file(to_wxid: str, file_url: str, file_name: str) -> dict:
    """
    发送文件消息
    :param to_wxid:   接收方ID
    :param file_url:  文件的公网可访问下载地址
    :param file_name: 文件名(含扩展名,如 contract.pdf)
    """
    url = f"{BASE}/message/postFile"
    payload = {
        "appId": APPID,
        "toWxid": to_wxid,
        "fileUrl": file_url,
        "fileName": file_name   # 字段名以官方文档为准
    }
    resp = requests.post(url, json=payload, headers=HEADERS, timeout=60)
    return resp.json()

result = send_file(
    "wxid_xxxxxxxx",
    "https://cdn.example.com/reports/Q2.pdf",
    "Q2业绩报告.pdf"
)

文件名编码fileName 字段务必使用 UTF-8 编码的字符串,若出现乱码,检查 Python 源文件编码声明及 requests 库的请求头 Content-Type 是否正确设置为 application/json; charset=utf-8

3.2 批量发文件的安全策略

批量给多人发同一份文件时,推荐"上传一次、转发多次"模式:

pythonimport time
import random

def batch_send_file(wxid_list: list, file_url: str, file_name: str):
    """
    批量发文件:第一条正常发,后续转发
    """
    first_msg_id = None
    first_from_wxid = None

    for i, wxid in enumerate(wxid_list):
        if i == 0:
            # 第一次正常上传发送
            res = send_file(wxid, file_url, file_name)
            if res.get("ret") == 200:
                first_msg_id = res["data"].get("msgId")
                first_from_wxid = APPID  # 自己发出的,以文档为准
        else:
            # 后续使用转发接口
            if first_msg_id:
                url = f"{BASE}/message/forwardFile"
                payload = {
                    "appId": APPID,
                    "toWxid": wxid,
                    "msgId": first_msg_id,
                    "fromWxid": first_from_wxid
                }
                requests.post(url, json=payload, headers=HEADERS, timeout=30)

        # 每条之间随机间隔,避免频控
        time.sleep(random.uniform(3, 10))

四、发送视频消息

视频消息使用 /message/postVideo 接口。视频文件体积通常较大,建议优先使用 URL 方式,并在服务器侧确保下载链接稳定可访问。

pythondef send_video(to_wxid: str, video_url: str, thumb_url: str = "") -> dict:
    """
    发送视频消息
    :param to_wxid:    接收方ID
    :param video_url:  视频公网地址(mp4 格式)
    :param thumb_url:  视频封面图 URL(可选,字段以文档为准)
    """
    url = f"{BASE}/message/postVideo"
    payload = {
        "appId": APPID,
        "toWxid": to_wxid,
        "videoUrl": video_url
    }
    if thumb_url:
        payload["thumbUrl"] = thumb_url

    resp = requests.post(url, json=payload, headers=HEADERS, timeout=120)
    return resp.json()

视频发送注意事项

  1. 格式:微信对视频格式有要求,建议提前转码为 H.264 编码的 mp4 文件。非标准格式可能导致接收方显示异常或无法播放,转码可使用 ffmpeg 在服务端自动处理。
  2. 大小:视频体积过大可能导致接口超时,建议单个视频控制在合理范围内(具体限制以文档为准)。超大视频可考虑先压缩分辨率或降低码率后再上传。
  3. timeout:视频上传耗时长,客户端超时设置建议不低于 90 秒。若使用异步任务队列,应将超时监控放在 worker 侧而非 HTTP 层。
  4. 封面图:传入 thumbUrl 可为视频指定封面,改善接收方的预览体验。封面图建议与视频宽高比一致,避免显示变形。
  5. 队列:批量发视频务必走队列,每条间隔 5-15 秒,禁止并发调用。

五、发送语音消息

语音消息使用 /message/postVoice 接口。微信语音格式要求较为严格,通常需要 SILKAMR 格式,其他格式(如 MP3)需在服务端转码后再发送。

pythondef send_voice(to_wxid: str, voice_url: str, duration: int) -> dict:
    """
    发送语音消息
    :param to_wxid:   接收方ID
    :param voice_url: 语音文件 URL(silk/amr 格式,以文档为准)
    :param duration:  语音时长(毫秒,字段名以文档为准)
    """
    url = f"{BASE}/message/postVoice"
    payload = {
        "appId": APPID,
        "toWxid": to_wxid,
        "voiceUrl": voice_url,
        "voiceDuration": duration  # 字段名以官方文档为准
    }
    resp = requests.post(url, json=payload, headers=HEADERS, timeout=30)
    return resp.json()

# 示例:发送一段 8 秒的语音
send_voice("wxid_xxxxxxxx", "https://cdn.example.com/notice.silk", 8000)

语音格式转换参考

如果原始文件是 MP3,可通过 ffmpeg 转为 AMR:

bash# 安装 ffmpeg 后执行(仅供参考,具体参数视实际需求调整)
ffmpeg -i input.mp3 -ar 8000 -ac 1 -ab 12.2k output.amr

SILK 格式转换可借助开源工具 kn007/silk-v3-decoder(纯文字提及,不作链接),在本地完成转码后再上传。

语音时长字段voiceDuration 单位通常为毫秒,填写不准确会导致接收方播放进度条显示异常(时长偏长或偏短),应根据实际音频时长填写,而非估算值。可用 ffprobe 提取精确时长:

bashffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 output.amr

六、托管 HTTP API 的使用方案

如果不想自己搭建微信协议层,可以选择使用托管的 REST API 服务直接调用。该类平台提供扫码登录、消息收发、好友与群管理等 REST 接口,HTTP 调用即可,无需关心底层协议细节,适合快速验证或中小规模业务,例如 WechatApi

对接流程大致如下:

  1. 注册账号,调用 getLoginQrCode 获取二维码;
  2. 用微信扫码,通过 checkLogin 轮询确认登录状态,获得 appId
  3. 调用 setCallback 设置回调地址,接收消息推送;
  4. 使用上述 postImage / postFile / postVideo / postVoice 等接口发送媒体消息。

鉴权方式、接口域名、字段名称均以官方文档为准,不同版本可能存在差异。


七、频控与安全建议

微信对批量行为有严格的频控机制,媒体消息的发送同样需要注意节奏控制:

行为建议策略
批量发图/文件每条间隔 3-10 秒,随机化间隔
同一文件发多人首次 postFile,后续 forwardFile,避免重复上传
视频批量发送间隔不低于 10 秒,建议走任务队列
新登录设备建议在线稳定 3 天后再发起批量操作
异步处理回调收到回调立即返回 200,下载/转发在异步队列中处理

消息回调中收到媒体消息时,不要在回调函数内同步下载文件,这会阻塞回调响应,可能导致回调平台认为超时而重试,产生重复处理。正确做法是把 msgId 入队列,在异步 worker 中调用 downloadImage / downloadFile 等接口。

此外,新注册设备或长期离线重新上线的账号,建议先保持正常收发聊天若干天,再逐步开启自动化操作。频控触发后通常有冷却期,期间继续高频调用只会延长封控时间,应立即停止并等待恢复。


八、常见报错排查

错误现象可能原因排查方向
ret != 200,msg 提示"操作失败"频率过高触发频控降低调用频率,增加随机间隔
图片/视频发出但对方收不到设备不在线调用 checkOnline 确认登录状态
文件名乱码未传 fileName 或编码问题检查 fileName 字段是否为 UTF-8
语音消息发出但无声音格式不对确认使用 SILK/AMR,时长字段单位是否正确
视频接口超时视频文件过大或网络慢增大 timeout,压缩视频后重试
转发失败,提示 msgId 无效msgId 来自其他 appId确保 fromWxid 和 msgId 对应关系正确
Base64 上传返回体积超限图片/文件过大压缩后再编码,或改用 URL 方式
语音时长显示异常duration 字段填写有误用 ffprobe 获取精确毫秒时长后填写

总结

本文系统梳理了通过 REST 接口发送图片、文件、视频、语音四类媒体消息的完整方案。核心要点包括:优先使用 URL 方式传递媒体资源、通过"首次上传+后续转发"降低带宽和调用频率、语音和视频需提前确认格式和编码规范、批量操作必须引入随机间隔与异步队列以规避频控风险。掌握这些要点,可以在保持账号安全的前提下,高效构建微信富媒体自动化系统。

想动手试试?

WechatApi 提供扫码登录、消息收发、好友与群管理等 REST 接口,注册后几分钟跑通。

立即免费注册查看开发文档

相关产品页

🔗 微信机器人开发(产品页)🔗 微信客服机器人(产品页)🔗 微信群管理机器人(产品页)

相关文章

微信API接口返回失败/收不到消息?完整排查清单微信 API 怎么对接?Python 发出第一条消息实战Node.js 微信机器人开发教程(发消息 + 收回调)个人微信API能力清单:消息/好友/群/朋友圈接口一览
© 2025 WechatApi · 企业级微信智能机器人接入平台
官网价格帮助文档博客
苏ICP备2024128799号 · 苏ICP备2023038368号