linwe
2024-07-29 aeb7d068be92312dcdcea75e1240bcf2a78dd0fe
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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
package org.springblade.common.utils;
 
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.web.multipart.MultipartFile;
 
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.io.FileUtils;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import net.coobird.thumbnailator.Thumbnails;
 
/**
 * 微信安全检验工具类
 */
public class WeiXinSecurityUtil {
    private static Integer IMG_WIDTH = 750;
    private static Integer IMG_HEIGHT = 1334;
    /**
     * 图片检测接口
     */
    private static String IMG_SEC_URL = "https://api.weixin.qq.com/wxa/img_sec_check?access_token=";
 
    //获取wxAccessToken
    private static String WX_GET_ACCESS_TOKEN = "https://api.weixin.qq.com/cgi-bin/token";
 
    private static String WX_APP_ID = "wx41aa8a5d2e565a05";
    private static String WX_SECRET = "e0e9218ac368cd4ca620ff4c7030f468";
 
    /**
     * 恶意图片过滤-校验图片是否含有违法违规内容
     * MultipartFile multipartFile, String accessToken
     * @param multipartFile
     * @return
     */
    public static String checkImg(MultipartFile multipartFile){
        String result = "";
        //压缩图片
        InputStream inputStream = compressImage(multipartFile);
        // 校验api url
        String url = IMG_SEC_URL + getWxAccessToken();
        // 获得Http客户端(可以理解为:你得先有一个浏览器;注意:实际上HttpClient与浏览器是不一样的
        HttpClient httpclient = HttpClients.createDefault();
        //创建一个post请求
        HttpPost request = new HttpPost(url);
        //设置响应头   ( application/octet-stream:二进制流,不知道下载文件类型)
        request.addHeader("Content-Type", "application/octet-stream");
        try {
            //创建一个byte数组,和输入的文件的大小一样
            byte[] byt = new byte[inputStream.available()];
            //从输入流中读取全部,并将其存储在缓冲区数组byt 中。
            inputStream.read(byt);
            //定制提交内容
            request.setEntity(new ByteArrayEntity(byt, ContentType.create("image/jpg")));
            //由客户端执行(发送)请求,执行校验
            HttpResponse response = httpclient.execute(request);
            // 从响应模型中获取响应实体
            HttpEntity entity = response.getEntity();
            result = EntityUtils.toString(entity, "UTF-8");// 转成string
            //打印校验结果
            System.out.println("result:" + result);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(inputStream != null){
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        // 响应返回结果
        return result;
    }
 
 
 
    /**
     * 图片过滤检测
     * @param file 图片文件
     * @return
     */
    public String checkPic(MultipartFile file) {
        String access_token = "";
        String result = "";
        //自己写一个定时任务或其他方式 获取AccessToken
        try {
            access_token = getWxAccessToken();
            String url = "https://api.weixin.qq.com/wxa/img_sec_check?access_token=" + access_token;
            result = uploadFile(url, file);
            System.out.println("图片检测结果 = " + result);
        } catch (Exception e) {
            System.out.println("----------------调用腾讯内容过滤系统出错------------------" + e.getMessage());
        }
        // 返回
        return result;
    }
 
    /**
     * 上传二进制文件
     * @param graphurl 接口地址
     * @param file 图片文件
     * @return
     */
    public static String uploadFile(String graphurl,MultipartFile file) {
        String line = null;//接口返回的结果
        try {
            // 换行符
            final String newLine = "\r\n";
            final String boundaryPrefix = "--";
            // 定义数据分隔线
            String BOUNDARY = "========7d4a6d158c9";
            // 服务器的域名
            URL url = new URL(graphurl);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            // 设置为POST情
            conn.setRequestMethod("POST");
            // 发送POST请求必须设置如下两行
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setUseCaches(false);
            // 设置请求头参数
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("Charsert", "UTF-8");
            conn.setRequestProperty("Content-Type","multipart/form-data; boundary=" + BOUNDARY);
            conn.setRequestProperty("User-Agent","Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1");
            OutputStream out = new DataOutputStream(conn.getOutputStream());
 
            // 上传文件
            StringBuilder sb = new StringBuilder();
            sb.append(boundaryPrefix);
            sb.append(BOUNDARY);
            sb.append(newLine);
            // 文件参数,photo参数名可以随意修改
            sb.append("Content-Disposition: form-data;name=\"image\";filename=\""
                + "https://api.weixin.qq.com" + "\"" + newLine);
            sb.append("Content-Type:application/octet-stream");
            // 参数头设置完以后需要两个换行,然后才是参数内容
            sb.append(newLine);
            sb.append(newLine);
 
            // 将参数头的数据写入到输出流中
            out.write(sb.toString().getBytes());
 
            // 读取文件数据
            out.write(file.getBytes());
            // 最后添加换行
            out.write(newLine.getBytes());
 
            // 定义最后数据分隔线,即--加上BOUNDARY再加上--。
            byte[] end_data = (newLine + boundaryPrefix + BOUNDARY
                + boundaryPrefix + newLine).getBytes();
            // 写上结尾标识
            out.write(end_data);
            out.flush();
            out.close();
            // 定义BufferedReader输入流来读取URL的响应
            BufferedReader reader = new BufferedReader(new InputStreamReader(
                conn.getInputStream()));
            while ((line = reader.readLine()) != null) {
                return line;
            }
        } catch (Exception e) {
            System.out.println("发送POST请求出现异常!" + e);
        }
        return line;
    }
 
    /**
     * 上传二进制文件
     * @param apiurl 接口地址
     * @param file 图片文件
     * @return
     */
    public static String uploadFile(String apiurl, byte[] file) {
        //接口返回的结果
        String line = null;
        try {
            // 换行符
            final String newLine = "\r\n";
            final String boundaryPrefix = "--";
            // 定义数据分隔线
            String BOUNDARY = "========7d4a6d158c9";
            // 服务器的域名
            URL url = new URL(apiurl);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            // 设置为POST情
            conn.setRequestMethod("POST");
            // 发送POST请求必须设置如下两行
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setUseCaches(false);
            // 设置请求头参数
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("Charsert", "UTF-8");
            conn.setRequestProperty("Content-Type","multipart/form-data; boundary=" + BOUNDARY);
            conn.setRequestProperty("User-Agent","Mozilla/5.0 (iPhone; CPU iPhone OS 14_0_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/7.0.15(0x17000f31) NetType/WIFI Language/zh_CN");
            OutputStream out = new DataOutputStream(conn.getOutputStream());
 
            // 上传文件
            StringBuilder sb = new StringBuilder();
            sb.append(boundaryPrefix);
            sb.append(BOUNDARY);
            sb.append(newLine);
            // 文件参数,photo参数名可以随意修改
            sb.append("Content-Disposition: form-data;name=\"image\";filename=\""
                + "https://api.weixin.qq.com" + "\"" + newLine);
            sb.append("Content-Type:application/octet-stream");
            // 参数头设置完以后需要两个换行,然后才是参数内容
            sb.append(newLine);
            sb.append(newLine);
 
            // 将参数头的数据写入到输出流中
            out.write(sb.toString().getBytes());
 
            // 读取文件数据
            out.write(file);
            // 最后添加换行
            out.write(newLine.getBytes());
 
            // 定义最后数据分隔线,即--加上BOUNDARY再加上--。
            byte[] end_data = (newLine + boundaryPrefix + BOUNDARY
                + boundaryPrefix + newLine).getBytes();
            // 写上结尾标识
            out.write(end_data);
            out.flush();
            out.close();
            // 定义BufferedReader输入流来读取URL的响应
            BufferedReader reader = new BufferedReader(new InputStreamReader(
                conn.getInputStream()));
            while ((line = reader.readLine()) != null) {
                return line;
            }
        } catch (Exception e) {
            System.out.println("发送POST请求出现异常!" + e);
        }
        return line;
    }
 
    /**
     * 获取 WxAccessToken
     * @return
     */
    public static String getWxAccessToken() {
        //参数
        Map<String, String> params = new HashMap<>();
        params.put("grant_type", "client_credential");
        params.put("appid", WX_APP_ID);
        params.put("secret", WX_SECRET);
        String result = HttpClientUtils.doGet(WX_GET_ACCESS_TOKEN, params);
        JSONObject jsonObject = JSON.parseObject(result);
        String accessToken = jsonObject.getString("access_token");
        return accessToken;
    }
 
 
 
    /**
     * 压缩图片
     * @param multipartFile
     */
    public static InputStream compressImage(MultipartFile multipartFile){
        //*************对不是jpg格式的图片转换成jpg格式***************
        //获取文件名后缀,判断其格式
        int begin = multipartFile.getOriginalFilename().lastIndexOf(".");
        int last = multipartFile.getOriginalFilename().length();
        //获得文件后缀名
        String houzuiFileName = multipartFile.getOriginalFilename().substring(begin, last);
        //创建临时文件
        File tempFile = new File(multipartFile.getOriginalFilename());
        //写入临时File文件 tempFile,将multipartFile转换成File
        try {
            //import org.apache.commons.io.FileUtils;
            FileUtils.copyInputStreamToFile(multipartFile.getInputStream(), tempFile);
        } catch (IOException e) {
            e.printStackTrace();
        }
        //如果文件不是jpg格式,转换其格式
        if (!"jpg".equalsIgnoreCase(houzuiFileName)){
            //ImageUtils是一个工具类,下面给出
            //将png格式转换成jpg,输出到tempFile
            //测试OK
            ImageUtils.convert(multipartFile.getOriginalFilename(), "jpg", tempFile.getAbsolutePath());
            //*************对不是jpg格式的图片转换成jpg格式***************
        }
        try {
            //压缩图片
            BufferedImage bufferedImage = Thumbnails.of(tempFile)
                .size(740, 1330)//指定压缩之后的图片尺寸
                .outputQuality(0.8f)//图片压缩质量
                .asBufferedImage();
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            ImageIO.write(bufferedImage, "jpg", os);
            InputStream inputStream = new ByteArrayInputStream(os.toByteArray());
//            System.out.println(inputStream);
            return inputStream;
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
//             会在本地产生临时文件,用完后需要删除
            if (tempFile.exists()) {
                tempFile.delete();
            }
        }
        return null;
    }
 
}