目录
一. 前言
当我们在企业微信创建了群机器人后,除了发送基本的文字类型的消息外,也是可以发送文件到群里的。具体流程分为两步:第一步先把文件调用企业微信官方文件上传接口上传文件到服务器(上传成功后会返回media_id),第二步把上传成功后返回的media_id调用企业微信官方发送消息的接口发送到对应群机器人群即可。
企业微信群机器人官方API地址:群机器人配置说明 - 接口文档 - 企业微信开发者中心
二. 具体步骤:
1. 上传文件
把需要发送到群里的文件先调用上传接口上传到服务器。
上传接口:https://qyapi.weixin.qq.com/cgi-bin/webhook/upload_media?key=KEY&type=TYPE
KEY: 调用接口凭证, 机器人webhookurl中的key参数,直接在企业微信双击群机器人查看(创建者才有查看权限)
TYPE: 文件类型,分别有语音(voice)和普通文件(file)
以下为官方文件上传接口说明(参考):
文件上传接口
素材上传得到media_id,该media_id仅三天内有效
media_id只能是对应上传文件的机器人可以使用请求方式:POST(HTTPS)
请求地址:https://qyapi.weixin.qq.com/cgi-bin/webhook/upload_media?key=KEY&type=TYPE使用multipart/form-data POST上传文件或语音, 文件标识名为"media"
参数说明:
参数 必须 说明 key 是 调用接口凭证, 机器人webhookurl中的key参数 type 是 文件类型,分别有语音(voice)和普通文件(file) POST的请求包中,form-data中媒体文件标识,应包含有 filename、filelength、content-type等信息
filename标识文件展示的名称。比如,使用该media_id发消息时,展示的文件名由该字段控制请求示例:
返回数据:
参数说明:
参数 说明 type 文件类型,分别有语音(voice)和普通文件(file) media_id 媒体文件上传后获取的唯一标识,3天内有效 created_at 媒体文件上传时间戳 上传的文件限制:
所有类型的文件大小均要求大于5个字节
- 普通文件(file):文件大小不超过20M
- 语音(voice):文件大小不超过2M,播放长度不超过60s,仅支持AMR格式
2. 发送消息
携带media_id并选择msgtype为file发送消息到群机器人接口
当文件上传成功后,我们可以把上传文件成功后返回的media_id,以及msgtype选择file类型发送信息到群机器人接口即可.
发送消息接口:https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=KEY
KEY: 调用接口凭证, 机器人webhookurl中的key参数
发送参数:
{
"msgtype": "file",
"file": {
"media_id": "3a8asd892asd8asd",(通过第一步获得)
}
}
参数 是否必填 说明 msgtype 是 消息类型,此时固定为file media_id 是 文件id,通过文件上传接口获取
三. 代码展示
(以发送excel到群机器人为例)
以下方法类可以直接copy使用,调用send接口,传入file,sendUrl,uploadUrl这三个参数即可,发送内容内部方法已经封装好,直接使用即可。
注:如缺失其他对应工具包,自行上网添加对应maven依赖即可。
<!--添加alibaba json工具类-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.83</version></dependency>
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
@Service
public class WorkWeixinNoticeByFileServiceImpl {
private static final Logger logger = LoggerFactory.getLogger(WorkWeixinNoticeByFileServiceImpl.class);
@Resource
private RestTemplate restTemplate;
/**
* 发送流程:
* 1.先调用企业微信文件上传接口将文件上传到服务器
* 2.上传完成后会返回一个media_id
* 3.用media_id发送到对应企业微信接口即可
*
* @param file 发送文件
* @param sendUrl 发送消息路径
* 例子:https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxx
* @param uploadUrl 文件上传路径
* 例子:https://qyapi.weixin.qq.com/cgi-bin/webhook/upload_media?key=xxx&type=file
* @return boolean
* @throws Exception
*/
public Boolean send(File file, String sendUrl, String uploadUrl) throws Exception {
boolean bool = true;
logger.info("企业微信机器人上传文件路径:{},发送文件路径:{}", uploadUrl, sendUrl);
ResponseEntity<Object> result = this.doUploadFile(uploadUrl, file);
logger.info("企业微信机器人上传结果返回值:{}",ObjectUtil.isNotEmpty(result) && ObjectUtil.isNotEmpty(result.getBody()) ? result.getBody().toString() : null);
JSONObject dataObject = JSONObject.parseObject(JSONObject.toJSONString(result.getBody()));
Integer errCode = Integer.valueOf(dataObject.get("errcode").toString());
if (ObjectUtil.isNotEmpty(errCode) && errCode.equals(0)) {
// 推送消息
String mediaId = (String) dataObject.get("media_id");
Map<String, Object> mediaMap = new HashMap<>();
mediaMap.put("media_id", mediaId);
Map<String, Object> msgMap = new HashMap<>();
msgMap.put("msgtype", "file");
msgMap.put("file", mediaMap);
ResponseEntity<Object> responseEntity = this.doPost(sendUrl, msgMap);
logger.info("企业微信机器人发送结果返回值:{}",ObjectUtil.isNotEmpty(responseEntity) && ObjectUtil.isNotEmpty(responseEntity.getBody()) ? responseEntity.getBody().toString() : null);
} else {
bool = false;
logger.error("企业微信机器人上传文件失败:{}", errCode);
}
return bool;
}
public ResponseEntity<Object> doPost(String url, Object data) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<JSONObject> httpEntity = new HttpEntity(data, headers);
return restTemplate.postForEntity(url, httpEntity, Object.class);
}
/**
* 上传文件
*
* @param url 发送路径
* @param file 上传文件
* @return object
*/
public ResponseEntity<Object> doUploadFile(String url, File file) {
// 1、封装请求头
HttpHeaders headers = new HttpHeaders();
MediaType type = MediaType.parseMediaType("multipart/form-data");
headers.setContentType(type);
headers.setContentLength(file.length());
headers.setContentDispositionFormData("media", file.getName());
// 2、封装请求体
MultiValueMap<String, Object> param = new LinkedMultiValueMap<>();
FileSystemResource resource = new FileSystemResource(file);
param.add("file", resource);
// 3、封装整个请求报文
HttpEntity<MultiValueMap<String, Object>> formEntity = new HttpEntity<>(param, headers);
return restTemplate.postForEntity(url, formEntity, Object.class);
}
}
四. 效果
在对应的企业微信群发送了一个excel文件