zxl
5 天以前 2701dca44e1972afe9956ced2f949d2998c1bb4b
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
package cn.lili.modules.goods.util;
 
import cn.hutool.json.JSONObject;
import cn.lili.common.enums.ClientTypeEnum;
import cn.lili.common.enums.ResultCode;
import cn.lili.common.exception.ServiceException;
import cn.lili.modules.wechat.util.WechatAccessTokenUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
 
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
 
/**
 * 微信媒体工具
 *
 * @author Bulbasaur
 * @since 2021/5/19 8:02 下午
 */
@Slf4j
@Component
public class WechatMediaUtil {
    @Autowired
    private WechatAccessTokenUtil wechatAccessTokenUtil;
 
    /**
     * 上传多媒体数据到微信服务器
     *
     * @param mediaFileUrl 来自网络上面的媒体文件地址
     * @return
     */
    public String uploadMedia(String type, String mediaFileUrl) {
        //获取token
        String accessToken = wechatAccessTokenUtil.cgiAccessToken(ClientTypeEnum.WECHAT_MP);
        /*
         * 上传媒体文件到微信服务器需要请求的地址
         */
        String MEDIA_URL = "https://api.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE";
 
        StringBuffer resultStr = null;
        //拼装url地址
        String mediaStr = MEDIA_URL.replace("ACCESS_TOKEN", accessToken).replace("TYPE", type);
        URL mediaUrl;
        try {
            String boundary = "----WebKitFormBoundaryOYXo8heIv9pgpGjT";
            URL url = new URL(mediaStr);
            HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();
            //让输入输出流开启
            urlConn.setDoInput(true);
            urlConn.setDoOutput(true);
            //使用post方式请求的时候必须关闭缓存
            urlConn.setUseCaches(false);
            //设置请求头的Content-Type属性
            urlConn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
            urlConn.setRequestMethod("POST");
            //获取输出流,使用输出流拼接请求体
            OutputStream out = urlConn.getOutputStream();
 
            //读取文件的数据,构建一个GET请求,然后读取指定地址中的数据
            mediaUrl = new URL(mediaFileUrl);
            HttpURLConnection mediaConn = (HttpURLConnection) mediaUrl.openConnection();
            //设置请求方式
            mediaConn.setRequestMethod("GET");
            //设置可以打开输入流
            mediaConn.setDoInput(true);
            //获取传输的数据类型
            String contentType = mediaConn.getHeaderField("Content-Type");
            //将获取大到的类型转换成扩展名
            String fileExt = judgeType(contentType);
            //获取输入流,从mediaURL里面读取数据
            InputStream in = mediaConn.getInputStream();
            BufferedInputStream bufferedIn = new BufferedInputStream(in);
            //数据读取到这个数组里面
            byte[] bytes = new byte[1024];
            int size = 0;
            //使用outputStream流输出信息到请求体当中去
            out.write(("--" + boundary + "\r\n").getBytes());
            out.write(("Content-Disposition: form-data; name=\"media\";\r\n"
                    + "filename=\"" + (System.currentTimeMillis()) + fileExt + "\"\r\n"
                    + "Content-Type: " + contentType + "\r\n\r\n").getBytes());
            while ((size = bufferedIn.read(bytes)) != -1) {
                out.write(bytes, 0, size);
            }
            //切记,这里的换行符不能少,否则将会报41005错误
            out.write(("\r\n--" + boundary + "--\r\n").getBytes());
 
            bufferedIn.close();
            in.close();
            mediaConn.disconnect();
 
            InputStream resultIn = urlConn.getInputStream();
            InputStreamReader reader = new InputStreamReader(resultIn);
            BufferedReader bufferedReader = new BufferedReader(reader);
            String tempStr = null;
            resultStr = new StringBuffer();
            while ((tempStr = bufferedReader.readLine()) != null) {
                resultStr.append(tempStr);
            }
            bufferedReader.close();
            reader.close();
            resultIn.close();
            urlConn.disconnect();
        } catch (Exception e) {
            log.error("微信媒体上传失败", e);
        }
        assert resultStr != null;
        JSONObject jsonObject = new JSONObject(resultStr.toString());
        log.info("微信媒体上传:" + jsonObject);
        //判断是否传递成功,如果token过期则重新获取
        if (jsonObject.get("errcode") != null && ("40001").equals(jsonObject.get("errcode"))) {
            wechatAccessTokenUtil.removeAccessToken(ClientTypeEnum.WECHAT_MP);
            return this.uploadMedia(type, mediaFileUrl);
        } else if (jsonObject.get("errcode") != null) {
            throw new ServiceException(jsonObject.get("errmsg").toString());
        } else {
            return jsonObject.get("media_id").toString();
        }
 
    }
 
    /**
     * 通过传过来的contentType判断是哪一种类型
     *
     * @param contentType 获取来自连接的contentType
     * @return
     */
    public String judgeType(String contentType) {
        String fileExt = "";
        switch (contentType) {
            case "image/png":
                fileExt = ".png";
                break;
            case "image/jpeg":
                fileExt = ".jpeg";
                break;
            case "image/jpg":
                fileExt = ".jpg";
                break;
            default:
                throw new ServiceException(ResultCode.IMAGE_FILE_EXT_ERROR);
        }
        return fileExt;
    }
}