ChenJiaHe
2020-12-02 f0ed6f16d980c2110ea508b3ef446b0adbfc2864
提交 | 用户 | age
5c5945 1 package com.hx.util;
E 2
3 import net.sf.json.JSONException;
4 import net.sf.json.JSONObject;
5 import org.apache.commons.io.IOUtils;
6 import org.springframework.web.multipart.MultipartFile;
7
8 import javax.activation.MimetypesFileTypeMap;
9 import java.io.*;
10 import java.net.HttpURLConnection;
11 import java.net.URL;
12 import java.util.Iterator;
13 import java.util.List;
14 import java.util.Map;
15
16 /**
17  * http 工具类
18  */
19 public class HttpUtil {
20
21     /**multipart/form-data 格式发送数据时各个部分分隔符的前缀,必须为 --*/
22     private static final String BOUNDARY_PREFIX = "--";
23     /**回车换行,用于一行的结尾*/
24     private static final String LINE_END = "\r\n";
25
26
27     public static String post(String requestUrl, String accessToken, String params)
28             throws Exception {
29         String contentType = "application/x-www-form-urlencoded";
30         return HttpUtil.post(requestUrl, accessToken, contentType, params);
31     }
32
33     public static String post(String requestUrl, String accessToken, String contentType, String params)
34             throws Exception {
35         String encoding = "UTF-8";
36         if (requestUrl.contains("nlp")) {
37             encoding = "GBK";
38         }
39         return HttpUtil.post(requestUrl, accessToken, contentType, params, encoding);
40     }
41
42     public static String post(String requestUrl, String accessToken, String contentType, String params, String encoding)
43             throws Exception {
44         String url = requestUrl + "?access_token=" + accessToken;
45         return HttpUtil.postGeneralUrl(url, contentType, params, encoding);
46     }
47
48     public static String postGeneralUrl(String generalUrl, String contentType, String params, String encoding)
49             throws Exception {
50         URL url = new URL(generalUrl);
51         // 打开和URL之间的连接
52         HttpURLConnection connection = (HttpURLConnection) url.openConnection();
53         connection.setRequestMethod("POST");
54         // 设置通用的请求属性
55         connection.setRequestProperty("Content-Type", contentType);
56         connection.setRequestProperty("Connection", "Keep-Alive");
57         connection.setUseCaches(false);
58         connection.setDoOutput(true);
59         connection.setDoInput(true);
60
61         // 得到请求的输出流对象
62         DataOutputStream out = new DataOutputStream(connection.getOutputStream());
63         out.write(params.getBytes(encoding));
64         out.flush();
65         out.close();
66
67         // 建立实际的连接
68         connection.connect();
69         // 获取所有响应头字段
70         Map<String, List<String>> headers = connection.getHeaderFields();
71         // 遍历所有的响应头字段
72         for (String key : headers.keySet()) {
73             System.err.println(key + "--->" + headers.get(key));
74         }
75         // 定义 BufferedReader输入流来读取URL的响应
76         BufferedReader in = null;
77         in = new BufferedReader(
78                 new InputStreamReader(connection.getInputStream(), encoding));
79         String result = "";
80         String getLine;
81         while ((getLine = in.readLine()) != null) {
82             result += getLine;
83         }
84         in.close();
85         System.err.println("result:" + result);
86         return result;
87     }
88
89     /** 请求http协议 获取信息工具 **/
90     public static JSONObject HttpURLUtil(String url, String data) {
91         HttpURLConnection con = null;
92         URL u = null;
93         String wxMsgXml = null;
94         JSONObject obj = null;
95         try {
96             u = new URL(url);
97             con = (HttpURLConnection) u.openConnection();
98             con.setRequestMethod("POST");
99             con.setDoOutput(true);
100             con.setDoInput(true);
101             con.setUseCaches(false);
102             con.setReadTimeout(5000);
103             con.setRequestProperty("Charset", "UTF-8");
104             con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
105
106             if (data != null) {
107                 OutputStream os = con.getOutputStream();
108                 os.write(data.getBytes("utf-8"));
109             }
110
111             if (con.getResponseCode() != 200)
112                 throw new RuntimeException("请求url失败");
113             // 读取返回内容
114             wxMsgXml = IOUtils.toString(con.getInputStream(), "utf-8");
115             obj = JSONObject.fromObject(wxMsgXml);
116             // //System.out.println("HttpURLUtil:"+wxMsgXml);
117         } catch (Exception e) {
118             e.printStackTrace();
119             obj = new JSONObject();
120             try {
121                 obj.put("status", 1);
122                 obj.put("errMsg", e.getMessage());
123             } catch (JSONException e1) {
124                 e1.printStackTrace();
125             }
126         } finally {
127             if (con != null) {
128                 con.disconnect();
129             }
130         }
131         return obj;
132     }
133
134
135     /** 请求http协议 获取信息工具 **/
136     public static JSONObject HttpURLUtilJson(String url, String data) {
137         HttpURLConnection con = null;
138         URL u = null;
139         String wxMsgXml = null;
140         JSONObject obj = null;
141         try {
142             u = new URL(url);
143             con = (HttpURLConnection) u.openConnection();
144             con.setRequestMethod("POST");
145             con.setDoOutput(true);
146             con.setDoInput(true);
147             con.setUseCaches(false);
148             con.setReadTimeout(5000);
149             con.setRequestProperty("Charset", "UTF-8");
150             con.setRequestProperty("Content-Type", "application/json");
151
152             if (data != null) {
153                 OutputStream os = con.getOutputStream();
154                 os.write(data.getBytes("utf-8"));
155             }
156
157             if (con.getResponseCode() != 200)
158                 throw new RuntimeException("请求url失败");
159             // 读取返回内容
160             wxMsgXml = IOUtils.toString(con.getInputStream(), "utf-8");
161             obj = JSONObject.fromObject(wxMsgXml);
162             // //System.out.println("HttpURLUtil:"+wxMsgXml);
163         } catch (Exception e) {
164             e.printStackTrace();
165             obj = new JSONObject();
166             try {
167                 obj.put("status", 1);
168                 obj.put("errMsg", e.getMessage());
169             } catch (JSONException e1) {
170                 e1.printStackTrace();
171             }
172         } finally {
173             if (con != null) {
174                 con.disconnect();
175             }
176         }
177         return obj;
178     }
179
180     /**
181      * post 请求:以表单方式提交数据
182      * <p>
183      * 由于 multipart/form-data 不是 http 标准内容,而是属于扩展类型,
184      * 因此需要自己构造数据结构,具体如下:
185      * <p>
186      * 1、首先,设置 Content-Type
187      * <p>
188      * Content-Type: multipart/form-data; boundary=${bound}
189      * <p>
190      * 其中${bound} 是一个占位符,代表我们规定的分割符,可以自己任意规定,
191      * 但为了避免和正常文本重复了,尽量要使用复杂一点的内容
192      * <p>
193      * 2、设置主体内容
194      * <p>
195      * --${bound}
196      * Content-Disposition: form-data; name="userName"
197      * <p>
198      * Andy
199      * --${bound}
200      * Content-Disposition: form-data; name="file"; filename="测试.excel"
201      * Content-Type: application/octet-stream
202      * <p>
203      * 文件内容
204      * --${bound}--
205      * <p>
206      * 其中${bound}是之前头信息中的分隔符,如果头信息中规定是123,那这里也要是123;
207      * 可以很容易看到,这个请求提是多个相同部分组成的:
208      * 每一部分都是以--加分隔符开始的,然后是该部分内容的描述信息,然后一个回车换行,然后是描述信息的具体内容;
209      * 如果传送的内容是一个文件的话,那么还会包含文件名信息以及文件内容类型。
210      * 上面第二部分是一个文件体的结构,最后以--分隔符--结尾,表示请求体结束
211      *
212      * @param urlStr      请求的url
213      * @param filePathMap key 参数名,value 文件的路径
214      * @param keyValues   普通参数的键值对
215      * @param headers
216      * @return
217      * @throws IOException
218      */
219     public static HttpResponse postFormData(String urlStr, Map<String, String> filePathMap, Map<String, Object> keyValues, Map<String, Object> headers) throws IOException {
220         HttpResponse response;
221         HttpURLConnection conn = getHttpURLConnection(urlStr, headers);
222         //分隔符,可以任意设置,这里设置为 MyBoundary+ 时间戳(尽量复杂点,避免和正文重复)
223         String boundary = "MyBoundary" + System.currentTimeMillis();
224         //设置 Content-Type 为 multipart/form-data; boundary=${boundary}
225         conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
226
227         //发送参数数据
228         try (DataOutputStream out = new DataOutputStream(conn.getOutputStream())) {
229             //发送普通参数
230             if (keyValues != null && !keyValues.isEmpty()) {
231                 for (Map.Entry<String, Object> entry : keyValues.entrySet()) {
232                     writeSimpleFormField(boundary, out, entry);
233                 }
234             }
235             //发送文件类型参数
236             if (filePathMap != null && !filePathMap.isEmpty()) {
237                 for (Map.Entry<String, String> filePath : filePathMap.entrySet()) {
238                     writeFile(filePath.getKey(), filePath.getValue(), boundary, out);
239                 }
240             }
241
242             //写结尾的分隔符--${boundary}--,然后回车换行
243             String endStr = BOUNDARY_PREFIX + boundary + BOUNDARY_PREFIX + LINE_END;
244             out.write(endStr.getBytes());
245         } catch (Exception e) {
246             e.printStackTrace();
247             response = new HttpResponse(500, e.getMessage());
248             return response;
249         }
250
251         return getHttpResponse(conn);
252     }
253
254     public static HttpResponse postFormData(String urlStr, Map<String, MultipartFile> filePathMap, Map<String, Object> keyValues) throws IOException {
255         HttpResponse response;
256         HttpURLConnection conn = getHttpURLConnection(urlStr, null);
257         //分隔符,可以任意设置,这里设置为 MyBoundary+ 时间戳(尽量复杂点,避免和正文重复)
258         String boundary = "MyBoundary" + System.currentTimeMillis();
259         //设置 Content-Type 为 multipart/form-data; boundary=${boundary}
260         conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
261
262         //发送参数数据
263         try (DataOutputStream out = new DataOutputStream(conn.getOutputStream())) {
264             //发送普通参数
265             if (keyValues != null && !keyValues.isEmpty()) {
266                 for (Map.Entry<String, Object> entry : keyValues.entrySet()) {
267                     writeSimpleFormField(boundary, out, entry);
268                 }
269             }
270             //发送文件类型参数
271             if (filePathMap != null && !filePathMap.isEmpty()) {
272                 for (Map.Entry<String, MultipartFile> filePath : filePathMap.entrySet()) {
273                     writeFile(filePath.getKey(), filePath.getValue(), boundary, out);
274                 }
275             }
276
277             //写结尾的分隔符--${boundary}--,然后回车换行
278             String endStr = BOUNDARY_PREFIX + boundary + BOUNDARY_PREFIX + LINE_END;
279             out.write(endStr.getBytes());
280         } catch (Exception e) {
281             response = new HttpResponse(500, e.getMessage());
282             return response;
283         }
284
285         return getHttpResponse(conn);
286     }
287
288     /**
289      * 获得连接对象
290      *
291      * @param urlStr
292      * @param headers
293      * @return
294      * @throws IOException
295      */
296     private static HttpURLConnection getHttpURLConnection(String urlStr, Map<String, Object> headers) throws IOException {
297         URL url = new URL(urlStr);
298         HttpURLConnection conn = (HttpURLConnection) url.openConnection();
299         //设置超时时间
300         conn.setConnectTimeout(50000);
301         conn.setReadTimeout(50000);
302         //允许输入流
303         conn.setDoInput(true);
304         //允许输出流
305         conn.setDoOutput(true);
306         //不允许使用缓存
307         conn.setUseCaches(false);
308         //请求方式
309         conn.setRequestMethod("POST");
310         //设置编码 utf-8
311         conn.setRequestProperty("Charset", "UTF-8");
312         //设置为长连接
313         conn.setRequestProperty("connection", "keep-alive");
314
315         //设置其他自定义 headers
316         if (headers != null && !headers.isEmpty()) {
317             for (Map.Entry<String, Object> header : headers.entrySet()) {
318                 conn.setRequestProperty(header.getKey(), header.getValue().toString());
319             }
320         }
321
322         return conn;
323     }
324
325     private static HttpResponse getHttpResponse(HttpURLConnection conn) {
326         HttpResponse response;
327         try (BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()))) {
328             int responseCode = conn.getResponseCode();
329             StringBuilder responseContent = new StringBuilder();
330             String line;
331             while ((line = reader.readLine()) != null) {
332                 responseContent.append(line);
333             }
334             response = new HttpResponse(responseCode, responseContent.toString());
335         } catch (Exception e) {
336             e.printStackTrace();
337             response = new HttpResponse(500, e.getMessage());
338         }
339         return response;
340     }
341
342     /**
343      * 写文件类型的表单参数
344      *
345      * @param paramName 参数名
346      * @param filePath  文件路径
347      * @param boundary  分隔符
348      * @param out
349      * @throws IOException
350      */
351     private static void writeFile(String paramName, String filePath, String boundary,
352                                   DataOutputStream out) {
353         try (BufferedReader fileReader = new BufferedReader(new InputStreamReader(new FileInputStream(filePath)))) {
354             /**
355              * 写分隔符--${boundary},并回车换行
356              */
357             String boundaryStr = BOUNDARY_PREFIX + boundary + LINE_END;
358             out.write(boundaryStr.getBytes());
359             /**
360              * 写描述信息(文件名设置为上传文件的文件名):
361              * 写 Content-Disposition: form-data; name="参数名"; filename="文件名",并回车换行
362              * 写 Content-Type: application/octet-stream,并两个回车换行
363              */
364             String fileName = new File(filePath).getName();
365             String contentDispositionStr = String.format("Content-Disposition: form-data; name=\"%s\"; filename=\"%s\"", paramName, fileName) + LINE_END;
366             out.write(contentDispositionStr.getBytes());
367             String contentType = "Content-Type: application/octet-stream" + LINE_END + LINE_END;
368             out.write(contentType.getBytes());
369
370             String line;
371             while ((line = fileReader.readLine()) != null) {
372                 out.write(line.getBytes());
373             }
374             //回车换行
375             out.write(LINE_END.getBytes());
376         } catch (Exception e) {
377             e.printStackTrace();
378         }
379     }
380
381     /**
382      * 写文件类型的表单参数
383      *
384      * @param paramName 参数名
385      * @param multipartFile  文件
386      * @param boundary  分隔符
387      * @param out
388      * @throws IOException
389      */
390     private static void writeFile(String paramName, MultipartFile multipartFile, String boundary,
391                                   DataOutputStream out) {
392
393         try (BufferedReader fileReader = new BufferedReader(new InputStreamReader(multipartFile.getInputStream()))) {
394             /**
395              * 写分隔符--${boundary},并回车换行
396              */
397             String boundaryStr = BOUNDARY_PREFIX + boundary + LINE_END;
398             out.write(boundaryStr.getBytes());
399             /**
400              * 写描述信息(文件名设置为上传文件的文件名):
401              * 写 Content-Disposition: form-data; name="参数名"; filename="文件名",并回车换行
402              * 写 Content-Type: application/octet-stream,并两个回车换行
403              */
404             String fileName = multipartFile.getName();
405             String contentDispositionStr = String.format("Content-Disposition: form-data; name=\"%s\"; filename=\"%s\"", paramName, fileName) + LINE_END;
406             out.write(contentDispositionStr.getBytes());
407             String contentType = "Content-Type: application/octet-stream" + LINE_END + LINE_END;
408             out.write(contentType.getBytes());
409
410             String line;
411             while ((line = fileReader.readLine()) != null) {
412                 out.write(line.getBytes());
413             }
414             //回车换行
415             out.write(LINE_END.getBytes());
416         } catch (Exception e) {
417             e.printStackTrace();
418         }
419     }
420
421     /**
422      * 写普通的表单参数
423      *
424      * @param boundary 分隔符
425      * @param out
426      * @param entry    参数的键值对
427      * @throws IOException
428      */
429     private static void writeSimpleFormField(String boundary, DataOutputStream out, Map.Entry<String, Object> entry) throws IOException {
430         //写分隔符--${boundary},并回车换行
431         String boundaryStr = BOUNDARY_PREFIX + boundary + LINE_END;
432         out.write(boundaryStr.getBytes());
433         //写描述信息:Content-Disposition: form-data; name="参数名",并两个回车换行
434         String contentDispositionStr = String.format("Content-Disposition: form-data; name=\"%s\"", entry.getKey()) + LINE_END + LINE_END;
435         out.write(contentDispositionStr.getBytes());
436         //写具体内容:参数值,并回车换行
437         String valueStr = entry.getValue().toString() + LINE_END;
438         out.write(valueStr.getBytes());
439     }
440
441     public static String formUpload(String urlStr, Map<String, String> textMap,
442                                     Map<String, String> fileMap,String contentType) {
443         String res = "";
444         HttpURLConnection conn = null;
445         // boundary就是request头和上传文件内容的分隔符
446         String BOUNDARY = "---------------------------123821742118716";
447         try {
448             URL url = new URL(urlStr);
449             conn = (HttpURLConnection) url.openConnection();
450             conn.setConnectTimeout(5000);
451             conn.setReadTimeout(30000);
452             conn.setDoOutput(true);
453             conn.setDoInput(true);
454             conn.setUseCaches(false);
455             conn.setRequestMethod("POST");
456             conn.setRequestProperty("Connection", "Keep-Alive");
457             // conn.setRequestProperty("User-Agent","Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-CN; rv:1.9.2.6)");
458             conn.setRequestProperty("Content-Type","multipart/form-data; boundary=" + BOUNDARY);
459             OutputStream out = new DataOutputStream(conn.getOutputStream());
460             // text
461             if (textMap != null) {
462                 StringBuffer strBuf = new StringBuffer();
463                 Iterator iter = textMap.entrySet().iterator();
464                 while (iter.hasNext()) {
465                     Map.Entry entry = (Map.Entry) iter.next();
466                     String inputName = (String) entry.getKey();
467                     String inputValue = (String) entry.getValue();
468                     if (inputValue == null) {
469                         continue;
470                     }
471                     strBuf.append("\r\n").append("--").append(BOUNDARY).append("\r\n");
472                     strBuf.append("Content-Disposition: form-data; name=\"" + inputName + "\"\r\n\r\n");
473                     strBuf.append(inputValue);
474                 }
475                 out.write(strBuf.toString().getBytes());
476             }
477             // file
478             if (fileMap != null) {
479                 Iterator iter = fileMap.entrySet().iterator();
480                 while (iter.hasNext()) {
481                     Map.Entry entry = (Map.Entry) iter.next();
482                     String inputName = (String) entry.getKey();
483                     String inputValue = (String) entry.getValue();
484                     if (inputValue == null) {
485                         continue;
486                     }
487                     File file = new File(inputValue);
488                     String filename = file.getName();
489
490                     //没有传入文件类型,同时根据文件获取不到类型,默认采用application/octet-stream
491                     contentType = new MimetypesFileTypeMap().getContentType(file);
492                     //contentType非空采用filename匹配默认的图片类型
493                     if(!"".equals(contentType)){
494                         if (filename.endsWith(".png")) {
495                             contentType = "image/png";
496                         }else if (filename.endsWith(".jpg") || filename.endsWith(".jpeg") || filename.endsWith(".jpe")) {
497                             contentType = "image/jpeg";
498                         }else if (filename.endsWith(".gif")) {
499                             contentType = "image/gif";
500                         }else if (filename.endsWith(".ico")) {
501                             contentType = "image/image/x-icon";
502                         }
503                     }
504                     if (contentType == null || "".equals(contentType)) {
505                         contentType = "application/octet-stream";
506                     }
507                     StringBuffer strBuf = new StringBuffer();
508                     strBuf.append("\r\n").append("--").append(BOUNDARY).append("\r\n");
509                     strBuf.append("Content-Disposition: form-data; name=\"" + inputName + "\"; filename=\"" + filename + "\"\r\n");
510                     strBuf.append("Content-Type:" + contentType + "\r\n\r\n");
511                     out.write(strBuf.toString().getBytes());
512                     DataInputStream in = new DataInputStream(new FileInputStream(file));
513                     int bytes = 0;
514                     byte[] bufferOut = new byte[1024];
515                     while ((bytes = in.read(bufferOut)) != -1) {
516                         out.write(bufferOut, 0, bytes);
517                     }
518                     in.close();
519                 }
520             }
521             byte[] endData = ("\r\n--" + BOUNDARY + "--\r\n").getBytes();
522             out.write(endData);
523             out.flush();
524             out.close();
525             // 读取返回数据
526             StringBuffer strBuf = new StringBuffer();
527             BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
528             String line = null;
529             while ((line = reader.readLine()) != null) {
530                 strBuf.append(line).append("\n");
531             }
532             res = strBuf.toString();
533             reader.close();
534             reader = null;
535         } catch (Exception e) {
536             System.out.println("发送POST请求出错。" + urlStr);
537             e.printStackTrace();
538         } finally {
539             if (conn != null) {
540                 conn.disconnect();
541                 conn = null;
542             }
543         }
544         return res;
545     }
546 }