package com.hx.util; import net.sf.json.JSONException; import net.sf.json.JSONObject; import org.apache.commons.io.IOUtils; import org.bouncycastle.util.encoders.UTF8; import org.springframework.web.multipart.MultipartFile; import javax.activation.MimetypesFileTypeMap; import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServletRequest; import java.io.*; import java.net.HttpURLConnection; import java.net.URL; import java.nio.charset.Charset; import java.nio.charset.CharsetEncoder; import java.util.Iterator; import java.util.List; import java.util.Map; /** * http 工具类 */ public class HttpUtil { /**multipart/form-data 格式发送数据时各个部分分隔符的前缀,必须为 --*/ private static final String BOUNDARY_PREFIX = "--"; /**回车换行,用于一行的结尾*/ private static final String LINE_END = "\r\n"; public static String getInputStream(HttpServletRequest request) throws Exception { ServletInputStream stream = null; BufferedReader reader = null; StringBuffer sb = new StringBuffer(); try { stream = request.getInputStream(); // 获取响应 reader = new BufferedReader(new InputStreamReader(stream)); String line; while ((line = reader.readLine()) != null) { sb.append(line); } } catch (IOException e) { //logger.error(e); throw new RuntimeException("读取返回支付接口数据流出现异常!"); } finally { reader.close(); } //logger.info("输入流返回的内容:" + sb.toString()); return sb.toString(); } public static String post(String requestUrl, String accessToken, String params) throws Exception { String contentType = "application/x-www-form-urlencoded"; return HttpUtil.post(requestUrl, accessToken, contentType, params); } public static String post(String requestUrl, String accessToken, String contentType, String params) throws Exception { String encoding = "UTF-8"; if (requestUrl.contains("nlp")) { encoding = "GBK"; } return HttpUtil.post(requestUrl, accessToken, contentType, params, encoding); } public static String post(String requestUrl, String accessToken, String contentType, String params, String encoding) throws Exception { String url = requestUrl + "?access_token=" + accessToken; return HttpUtil.postGeneralUrl(url, contentType, params, encoding); } public static String postGeneralUrl(String generalUrl, String contentType, String params, String encoding) throws Exception { URL url = new URL(generalUrl); // 打开和URL之间的连接 HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("POST"); // 设置通用的请求属性 connection.setRequestProperty("Content-Type", contentType); connection.setRequestProperty("Connection", "Keep-Alive"); connection.setUseCaches(false); connection.setDoOutput(true); connection.setDoInput(true); // 得到请求的输出流对象 DataOutputStream out = new DataOutputStream(connection.getOutputStream()); out.write(params.getBytes(encoding)); out.flush(); out.close(); // 建立实际的连接 connection.connect(); // 获取所有响应头字段 Map> headers = connection.getHeaderFields(); // 遍历所有的响应头字段 for (String key : headers.keySet()) { System.err.println(key + "--->" + headers.get(key)); } // 定义 BufferedReader输入流来读取URL的响应 BufferedReader in = null; in = new BufferedReader( new InputStreamReader(connection.getInputStream(), encoding)); String result = ""; String getLine; while ((getLine = in.readLine()) != null) { result += getLine; } in.close(); System.err.println("result:" + result); return result; } /** * 带header的post请求 * @param generalUrl * @param header * @param params * @return * @throws Exception */ public static String post(String generalUrl, Map header, String params) throws Exception { URL url = new URL(generalUrl); // 打开和URL之间的连接 HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("POST"); // 设置通用的请求属性 connection.setRequestProperty("Connection", "Keep-Alive"); if(header != null) { for(String key : header.keySet()) { connection.setRequestProperty(key, header.get(key)); } } connection.setUseCaches(false); connection.setDoOutput(true); connection.setDoInput(true); // 得到请求的输出流对象 DataOutputStream out = new DataOutputStream(connection.getOutputStream()); out.write(params.getBytes("UTF-8")); out.flush(); out.close(); // 建立实际的连接 connection.connect(); // 定义 BufferedReader输入流来读取URL的响应 BufferedReader in = null; in = new BufferedReader( new InputStreamReader(connection.getInputStream(), "UTF-8")); String result = ""; String getLine; while ((getLine = in.readLine()) != null) { result += getLine; } in.close(); return result; } /** * 带header的get请求 * @param generalUrl * @param header * @return * @throws Exception */ public static String get(String generalUrl, Map header) throws Exception { URL url = new URL(generalUrl); // 打开和URL之间的连接 HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("GET"); // 设置通用的请求属性 connection.setRequestProperty("Connection", "Keep-Alive"); if(header != null) { for(String key : header.keySet()) { connection.setRequestProperty(key, header.get(key)); } } connection.setUseCaches(false); connection.setDoOutput(true); connection.setDoInput(true); // 建立实际的连接 connection.connect(); // 定义 BufferedReader输入流来读取URL的响应 BufferedReader in = null; in = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8")); String result = ""; String getLine; while ((getLine = in.readLine()) != null) { result += getLine; } in.close(); return result; } /** 请求http协议 获取信息工具 **/ public static JSONObject HttpURLUtil(String url, String data) { HttpURLConnection con = null; URL u = null; String wxMsgXml = null; JSONObject obj = null; try { u = new URL(url); con = (HttpURLConnection) u.openConnection(); con.setRequestMethod("POST"); con.setDoOutput(true); con.setDoInput(true); con.setUseCaches(false); con.setReadTimeout(5000); con.setRequestProperty("Charset", "UTF-8"); con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); if (data != null) { OutputStream os = con.getOutputStream(); os.write(data.getBytes("utf-8")); } if (con.getResponseCode() != 200) throw new RuntimeException("请求url失败"); // 读取返回内容 wxMsgXml = IOUtils.toString(con.getInputStream(), "utf-8"); obj = JSONObject.fromObject(wxMsgXml); // //System.out.println("HttpURLUtil:"+wxMsgXml); } catch (Exception e) { e.printStackTrace(); obj = new JSONObject(); try { obj.put("status", 1); obj.put("errMsg", e.getMessage()); } catch (JSONException e1) { e1.printStackTrace(); } } finally { if (con != null) { con.disconnect(); } } return obj; } /** 请求http协议 获取信息工具 **/ public static JSONObject HttpURLUtilJson(String url, String data) { HttpURLConnection con = null; URL u = null; String wxMsgXml = null; JSONObject obj = null; try { u = new URL(url); con = (HttpURLConnection) u.openConnection(); con.setRequestMethod("POST"); con.setDoOutput(true); con.setDoInput(true); con.setUseCaches(false); con.setReadTimeout(5000); con.setRequestProperty("Charset", "UTF-8"); con.setRequestProperty("Content-Type", "application/json"); if (data != null) { OutputStream os = con.getOutputStream(); os.write(data.getBytes("utf-8")); } if (con.getResponseCode() != 200) throw new RuntimeException("请求url失败"); // 读取返回内容 wxMsgXml = IOUtils.toString(con.getInputStream(), "utf-8"); obj = JSONObject.fromObject(wxMsgXml); // //System.out.println("HttpURLUtil:"+wxMsgXml); } catch (Exception e) { e.printStackTrace(); } finally { if (con != null) { con.disconnect(); } } return obj; } /** * post 请求:以表单方式提交数据 *

* 由于 multipart/form-data 不是 http 标准内容,而是属于扩展类型, * 因此需要自己构造数据结构,具体如下: *

* 1、首先,设置 Content-Type *

* Content-Type: multipart/form-data; boundary=${bound} *

* 其中${bound} 是一个占位符,代表我们规定的分割符,可以自己任意规定, * 但为了避免和正常文本重复了,尽量要使用复杂一点的内容 *

* 2、设置主体内容 *

* --${bound} * Content-Disposition: form-data; name="userName" *

* Andy * --${bound} * Content-Disposition: form-data; name="file"; filename="测试.excel" * Content-Type: application/octet-stream *

* 文件内容 * --${bound}-- *

* 其中${bound}是之前头信息中的分隔符,如果头信息中规定是123,那这里也要是123; * 可以很容易看到,这个请求提是多个相同部分组成的: * 每一部分都是以--加分隔符开始的,然后是该部分内容的描述信息,然后一个回车换行,然后是描述信息的具体内容; * 如果传送的内容是一个文件的话,那么还会包含文件名信息以及文件内容类型。 * 上面第二部分是一个文件体的结构,最后以--分隔符--结尾,表示请求体结束 * * @param urlStr 请求的url * @param filePathMap key 参数名,value 文件的路径 * @param keyValues 普通参数的键值对 * @param headers * @return * @throws IOException */ public static HttpResponse postFormData(String urlStr, Map filePathMap, Map keyValues, Map headers) throws IOException { HttpResponse response; HttpURLConnection conn = getHttpURLConnection(urlStr, headers); //分隔符,可以任意设置,这里设置为 MyBoundary+ 时间戳(尽量复杂点,避免和正文重复) String boundary = "MyBoundary" + System.currentTimeMillis(); //设置 Content-Type 为 multipart/form-data; boundary=${boundary} conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary); //发送参数数据 try (DataOutputStream out = new DataOutputStream(conn.getOutputStream())) { //发送普通参数 if (keyValues != null && !keyValues.isEmpty()) { for (Map.Entry entry : keyValues.entrySet()) { writeSimpleFormField(boundary, out, entry); } } //发送文件类型参数 if (filePathMap != null && !filePathMap.isEmpty()) { for (Map.Entry filePath : filePathMap.entrySet()) { writeFile(filePath.getKey(), filePath.getValue(), boundary, out); } } //写结尾的分隔符--${boundary}--,然后回车换行 String endStr = BOUNDARY_PREFIX + boundary + BOUNDARY_PREFIX + LINE_END; out.write(endStr.getBytes()); } catch (Exception e) { e.printStackTrace(); response = new HttpResponse(500, e.getMessage()); return response; } return getHttpResponse(conn); } public static HttpResponse postFormData(String urlStr, Map filePathMap, Map keyValues) throws IOException { HttpResponse response; HttpURLConnection conn = getHttpURLConnection(urlStr, null); //分隔符,可以任意设置,这里设置为 MyBoundary+ 时间戳(尽量复杂点,避免和正文重复) String boundary = "MyBoundary" + System.currentTimeMillis(); //设置 Content-Type 为 multipart/form-data; boundary=${boundary} conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary); //发送参数数据 try (DataOutputStream out = new DataOutputStream(conn.getOutputStream())) { //发送普通参数 if (keyValues != null && !keyValues.isEmpty()) { for (Map.Entry entry : keyValues.entrySet()) { writeSimpleFormField(boundary, out, entry); } } //发送文件类型参数 if (filePathMap != null && !filePathMap.isEmpty()) { for (Map.Entry filePath : filePathMap.entrySet()) { writeFile(filePath.getKey(), filePath.getValue(), boundary, out); } } //写结尾的分隔符--${boundary}--,然后回车换行 String endStr = BOUNDARY_PREFIX + boundary + BOUNDARY_PREFIX + LINE_END; out.write(endStr.getBytes()); } catch (Exception e) { response = new HttpResponse(500, e.getMessage()); return response; } return getHttpResponse(conn); } /** * 获得连接对象 * * @param urlStr * @param headers * @return * @throws IOException */ private static HttpURLConnection getHttpURLConnection(String urlStr, Map headers) throws IOException { URL url = new URL(urlStr); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); //设置超时时间 conn.setConnectTimeout(50000); conn.setReadTimeout(50000); //允许输入流 conn.setDoInput(true); //允许输出流 conn.setDoOutput(true); //不允许使用缓存 conn.setUseCaches(false); //请求方式 conn.setRequestMethod("POST"); //设置编码 utf-8 conn.setRequestProperty("Charset", "UTF-8"); //设置为长连接 conn.setRequestProperty("connection", "keep-alive"); //设置其他自定义 headers if (headers != null && !headers.isEmpty()) { for (Map.Entry header : headers.entrySet()) { conn.setRequestProperty(header.getKey(), header.getValue().toString()); } } return conn; } private static HttpResponse getHttpResponse(HttpURLConnection conn) { HttpResponse response; try (BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()))) { int responseCode = conn.getResponseCode(); StringBuilder responseContent = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { responseContent.append(line); } response = new HttpResponse(responseCode, responseContent.toString()); } catch (Exception e) { e.printStackTrace(); response = new HttpResponse(500, e.getMessage()); } return response; } /** * 写文件类型的表单参数 * * @param paramName 参数名 * @param filePath 文件路径 * @param boundary 分隔符 * @param out * @throws IOException */ private static void writeFile(String paramName, String filePath, String boundary, DataOutputStream out) { try (BufferedReader fileReader = new BufferedReader(new InputStreamReader(new FileInputStream(filePath)))) { /** * 写分隔符--${boundary},并回车换行 */ String boundaryStr = BOUNDARY_PREFIX + boundary + LINE_END; out.write(boundaryStr.getBytes()); /** * 写描述信息(文件名设置为上传文件的文件名): * 写 Content-Disposition: form-data; name="参数名"; filename="文件名",并回车换行 * 写 Content-Type: application/octet-stream,并两个回车换行 */ String fileName = new File(filePath).getName(); String contentDispositionStr = String.format("Content-Disposition: form-data; name=\"%s\"; filename=\"%s\"", paramName, fileName) + LINE_END; out.write(contentDispositionStr.getBytes()); String contentType = "Content-Type: application/octet-stream" + LINE_END + LINE_END; out.write(contentType.getBytes()); String line; while ((line = fileReader.readLine()) != null) { out.write(line.getBytes()); } //回车换行 out.write(LINE_END.getBytes()); } catch (Exception e) { e.printStackTrace(); } } /** * 写文件类型的表单参数 * * @param paramName 参数名 * @param multipartFile 文件 * @param boundary 分隔符 * @param out * @throws IOException */ private static void writeFile(String paramName, MultipartFile multipartFile, String boundary, DataOutputStream out) { try (BufferedReader fileReader = new BufferedReader(new InputStreamReader(multipartFile.getInputStream()))) { /** * 写分隔符--${boundary},并回车换行 */ String boundaryStr = BOUNDARY_PREFIX + boundary + LINE_END; out.write(boundaryStr.getBytes()); /** * 写描述信息(文件名设置为上传文件的文件名): * 写 Content-Disposition: form-data; name="参数名"; filename="文件名",并回车换行 * 写 Content-Type: application/octet-stream,并两个回车换行 */ String fileName = multipartFile.getName(); String contentDispositionStr = String.format("Content-Disposition: form-data; name=\"%s\"; filename=\"%s\"", paramName, fileName) + LINE_END; out.write(contentDispositionStr.getBytes()); String contentType = "Content-Type: application/octet-stream" + LINE_END + LINE_END; out.write(contentType.getBytes()); String line; while ((line = fileReader.readLine()) != null) { out.write(line.getBytes()); } //回车换行 out.write(LINE_END.getBytes()); } catch (Exception e) { e.printStackTrace(); } } /** * 写普通的表单参数 * * @param boundary 分隔符 * @param out * @param entry 参数的键值对 * @throws IOException */ private static void writeSimpleFormField(String boundary, DataOutputStream out, Map.Entry entry) throws IOException { //写分隔符--${boundary},并回车换行 String boundaryStr = BOUNDARY_PREFIX + boundary + LINE_END; out.write(boundaryStr.getBytes()); //写描述信息:Content-Disposition: form-data; name="参数名",并两个回车换行 String contentDispositionStr = String.format("Content-Disposition: form-data; name=\"%s\"", entry.getKey()) + LINE_END + LINE_END; out.write(contentDispositionStr.getBytes()); //写具体内容:参数值,并回车换行 String valueStr = entry.getValue().toString() + LINE_END; out.write(valueStr.getBytes()); } public static String formUpload(String urlStr, Map textMap, Map fileMap,String contentType) { String res = ""; HttpURLConnection conn = null; // boundary就是request头和上传文件内容的分隔符 String BOUNDARY = "---------------------------123821742118716"; try { URL url = new URL(urlStr); conn = (HttpURLConnection) url.openConnection(); conn.setConnectTimeout(5000); conn.setReadTimeout(30000); conn.setDoOutput(true); conn.setDoInput(true); conn.setUseCaches(false); conn.setRequestMethod("POST"); conn.setRequestProperty("Connection", "Keep-Alive"); // conn.setRequestProperty("User-Agent","Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-CN; rv:1.9.2.6)"); conn.setRequestProperty("Content-Type","multipart/form-data; boundary=" + BOUNDARY); OutputStream out = new DataOutputStream(conn.getOutputStream()); // text if (textMap != null) { StringBuffer strBuf = new StringBuffer(); Iterator iter = textMap.entrySet().iterator(); while (iter.hasNext()) { Map.Entry entry = (Map.Entry) iter.next(); String inputName = (String) entry.getKey(); String inputValue = (String) entry.getValue(); if (inputValue == null) { continue; } strBuf.append("\r\n").append("--").append(BOUNDARY).append("\r\n"); strBuf.append("Content-Disposition: form-data; name=\"" + inputName + "\"\r\n\r\n"); strBuf.append(inputValue); } out.write(strBuf.toString().getBytes()); } // file if (fileMap != null) { Iterator iter = fileMap.entrySet().iterator(); while (iter.hasNext()) { Map.Entry entry = (Map.Entry) iter.next(); String inputName = (String) entry.getKey(); String inputValue = (String) entry.getValue(); if (inputValue == null) { continue; } File file = new File(inputValue); String filename = file.getName(); //没有传入文件类型,同时根据文件获取不到类型,默认采用application/octet-stream contentType = new MimetypesFileTypeMap().getContentType(file); //contentType非空采用filename匹配默认的图片类型 if(!"".equals(contentType)){ if (filename.endsWith(".png")) { contentType = "image/png"; }else if (filename.endsWith(".jpg") || filename.endsWith(".jpeg") || filename.endsWith(".jpe")) { contentType = "image/jpeg"; }else if (filename.endsWith(".gif")) { contentType = "image/gif"; }else if (filename.endsWith(".ico")) { contentType = "image/image/x-icon"; } } if (contentType == null || "".equals(contentType)) { contentType = "application/octet-stream"; } StringBuffer strBuf = new StringBuffer(); strBuf.append("\r\n").append("--").append(BOUNDARY).append("\r\n"); strBuf.append("Content-Disposition: form-data; name=\"" + inputName + "\"; filename=\"" + filename + "\"\r\n"); strBuf.append("Content-Type:" + contentType + "\r\n\r\n"); out.write(strBuf.toString().getBytes()); DataInputStream in = new DataInputStream(new FileInputStream(file)); int bytes = 0; byte[] bufferOut = new byte[1024]; while ((bytes = in.read(bufferOut)) != -1) { out.write(bufferOut, 0, bytes); } in.close(); } } byte[] endData = ("\r\n--" + BOUNDARY + "--\r\n").getBytes(); out.write(endData); out.flush(); out.close(); // 读取返回数据 StringBuffer strBuf = new StringBuffer(); BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream())); String line = null; while ((line = reader.readLine()) != null) { strBuf.append(line).append("\n"); } res = strBuf.toString(); reader.close(); reader = null; } catch (Exception e) { System.out.println("发送POST请求出错。" + urlStr); e.printStackTrace(); } finally { if (conn != null) { conn.disconnect(); conn = null; } } return res; } }