文章目录

  • 前言
  • 一、获取上传的临时素材
  • 二、使用步骤
  • 1.引入库以及工具类
  • 2.实现代码
  • 总结



前言

根据之前上传的临时素材会拿到一个media_id,该media_id仅三天内有效
既然有上传,是不是得有获取。接下来就看看获取的方法。


一、获取上传的临时素材

根据media_id拿到企业微信的文件流,后台经过处理,保存服务器或者返回流给前端,前端下载到本地。

二、使用步骤

1.引入库以及工具类

我这里使用了Hutool工具包

<!-- hutool工具包 -->
<dependency>
	<groupId>cn.hutool</groupId>
	<artifactId>hutool-all</artifactId>
	<version>5.4.6</version>
</dependency>

处理文件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];
    }
}

2.实现代码

先了解官方说明:
请求方式: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代理端口,不需要代理的可以去掉


总结

就是对文件流的一个处理,还有一个信任管理器