根据之前上传的临时素材会拿到一个media_id,该media_id仅三天内有效
既然有上传,是不是得有获取。接下来就看看获取的方法。
根据media_id拿到企业微信的文件流,后台经过处理,保存服务器或者返回流给前端,前端下载到本地。
我这里使用了Hutool工具包
cn.hutool
hutool-all
5.4.6
处理文件WeiXinUtil.java的公具类
package com.example.util;
import java.io.*;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.URL;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import lombok.extern.slf4j.Slf4j;
/**
* TOO
*
* @author hj
* @version 1.0
*/
@Slf4j
public class WeiXinUtil {
/**
* 发送https请求之获取临时素材
* @param requestUrl
* @param savePath 文件的保存路径,此时还缺一个扩展名
* @return
* @throws Exception
*/
public static File getFile(String requestUrl,String savePath,String httpProxyHost,Integer httpProxyPort) throws Exception {
// 创建SSLContext对象,并使用我们指定的信任管理器初始化
TrustManager[] tm = { new MyX509TrustManager() };
SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
sslContext.init(null, tm, new java.security.SecureRandom());
// 从上述SSLContext对象中得到SSLSocketFactory对象
SSLSocketFactory ssf = sslContext.getSocketFactory();
URL url = new URL(requestUrl);
//创建代理服务器
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(httpProxyHost, httpProxyPort));
//把代理加入请求链接
HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection(proxy);
httpUrlConn.setSSLSocketFactory(ssf);
httpUrlConn.setDoOutput(true);
httpUrlConn.setDoInput(true);
httpUrlConn.setUseCaches(false);
// 设置请求方式(GET/POST)
httpUrlConn.setRequestMethod("GET");
httpUrlConn.connect();
//获取文件扩展名
String ext = getExt(httpUrlConn.getContentType());
//设置文件名
savePath = savePath + System.currentTimeMillis() + ext;
log.info("savePath:{}",savePath);
//下载文件到f文件
File file = new File(savePath);
// 获取微信返回的输入流
InputStream in = httpUrlConn.getInputStream();
//输出流,将微信返回的输入流内容写到文件中
FileOutputStream out = new FileOutputStream(file);
int length=100*1024;
byte[] byteBuffer = new byte[length]; //存储文件内容
int byteread =0;
int bytesum=0;
while (( byteread=in.read(byteBuffer)) != -1) {
bytesum += byteread; //字节数 文件大小
out.write(byteBuffer,0,byteread);
}
log.info("bytesum:{}",bytesum);
in.close();
// 释放资源
out.close();
in = null;
out=null;
httpUrlConn.disconnect();
return file;
}
/**
* 获取文件扩展名
* @param contentType
* @return
*/
private static String getExt(String contentType){
if("image/jpeg".equals(contentType)){
return ".jpg";
}else if("image/png".equals(contentType)){
return ".png";
}else if("image/gif".equals(contentType)){
return ".gif";
}
return null;
}
}
信任管理器
package com.example.util;
import javax.net.ssl.X509TrustManager;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
/**
* TOO
* 信任管理器
* @author hj
* @version 1.0
*/
public class MyX509TrustManager implements X509TrustManager {
@Override
public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
}
先了解官方说明:
请求方式:GET(HTTPS)
请求地址:https://qyapi.weixin.qq.com/cgi-bin/media/get?access_token=ACCESS_TOKEN&media_id=MEDIA_ID
参数说明 :
参数 | 必须 | 说明 |
---|---|---|
access_token | 是 | 调用接口凭证 |
media_id | 是 | 媒体文件id, 见上传临时素材 |
权限说明:
完全公开,media_id在同一企业内所有应用之间可以共享。
先看接口层代码:controller
我这里是直接返回的文件流,pc端打卡会下载。
package com.example.controller.material;
import com.alibaba.fastjson.JSONObject;
import com.example.dto.material.dto.MaterialUploadDTO;
import com.example.dto.material.dto.MediaGetDTO;
import com.example.service.MaterialService;
import com.example.util.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
/**
* TOO
* 素材管理
* @author hj
* @version 1.0
*/
@RestController
@RequestMapping("/material/media/api")
@Api(tags = "素材管理")
@Slf4j
public class MaterialManageController {
@Autowired
private MaterialService materialService;
@PostMapping(value = "/mediaGet")
@ApiOperation("获取临时素材")
public void mediaGet(@RequestBody MediaGetDTO mediaGetDTO,HttpServletRequest request, HttpServletResponse response) throws Exception{
File file = materialService.mediaGet(mediaGetDTO);
response.setContentType("application/octet-stream");
response.setHeader("Content-disposition", "attachment;filename=" + file.getName());
response.setHeader("Content-Length", String.valueOf(file.length()));
request.setCharacterEncoding("UTF-8");
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream());
byte[] buff = new byte[2048];
int bytesRead;
while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
bos.write(buff, 0, bytesRead);
}
bis.close();
bos.close();
}
}
服务类:MaterialService
package com.example.service;
import com.example.dto.material.dto.MaterialUploadDTO;
import com.example.dto.material.dto.MediaGetDTO;
import com.example.util.Result;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
/**
* TOO
* 素材管理
* @author hj
* @version 1.0
*/
public interface MaterialService {
//获取临时素材
File mediaGet(MediaGetDTO mediaGetDTO);
}
实现类:MaterialServiceImpl
package com.example.service.impl;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson.JSONObject;
import com.example.dto.common.ResponseHead;
import com.example.dto.material.dto.MaterialUploadDTO;
import com.example.dto.material.dto.MediaGetDTO;
import com.example.exception.BusinessException;
import com.example.service.MaterialService;
import com.example.service.TWxAccessTokenService;
import com.example.util.MapUtil;
import com.example.util.Result;
import com.example.util.WeiXinUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
/**
* TOO
* 素材管理-实现类
* @author hj
* @version 1.0
*/
@Service
@Slf4j
public class MaterialServiceImpl implements MaterialService {
@Autowired
private TWxAccessTokenService tWxAccessTokenService;
@Value("${wechat.material.mediaGet}")
private String mediaGet;
@Value("${basePath}")
private String basePath;
@Value("${wechat.corpFlag}")
private String corpFlag;
@Value("${wechat.cp.httpProxyHost}")
private String httpProxyHost;
@Value("${wechat.cp.httpProxyPort}")
private Integer httpProxyPort;
/**
* 获取临时素材
* @param mediaGetDTO
* @return
*/
@Override
public File mediaGet(MediaGetDTO mediaGetDTO) {
String accessToken = tWxAccessTokenService.getAccessToken(corpFlag,mediaGetDTO.getRequestHead().getConsumerID());
if(StrUtil.isBlank(accessToken)){
throw new BusinessException(Result.success(ResponseHead.error("请检查consumerID!")));
}
String url = mediaGet.replace("ACCESS_TOKEN",accessToken).replace("MEDIA_ID",mediaGetDTO.getRequestBody().getMedia_id());
File file;
try {
file = WeiXinUtil.getFile(url,basePath,httpProxyHost,httpProxyPort);
return file;
}catch (Exception e){
e.printStackTrace();
}
return null;
}
}
其实上面最核心的代码就在WeiXinUtil.getFile(url,basePath,httpProxyHost,httpProxyPort);方法上。
1:url是企业微信的获取地址
2:basePath是传入的服务器地址,不管是本地还是你到时候部署的服务器,都需要提供一个地址用作缓存。可以理解为临时目录。
3:httpProxyHost这是我代理的ip地址,如果不需要代理的可以去掉
4:httpProxyPort代理端口,不需要代理的可以去掉
就是对文件流的一个处理,还有一个信任管理器