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