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<String, List<String>> 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<String, String> 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<String, String> 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 请求:以表单方式提交数据
|
* <p>
|
* 由于 multipart/form-data 不是 http 标准内容,而是属于扩展类型,
|
* 因此需要自己构造数据结构,具体如下:
|
* <p>
|
* 1、首先,设置 Content-Type
|
* <p>
|
* Content-Type: multipart/form-data; boundary=${bound}
|
* <p>
|
* 其中${bound} 是一个占位符,代表我们规定的分割符,可以自己任意规定,
|
* 但为了避免和正常文本重复了,尽量要使用复杂一点的内容
|
* <p>
|
* 2、设置主体内容
|
* <p>
|
* --${bound}
|
* Content-Disposition: form-data; name="userName"
|
* <p>
|
* Andy
|
* --${bound}
|
* Content-Disposition: form-data; name="file"; filename="测试.excel"
|
* Content-Type: application/octet-stream
|
* <p>
|
* 文件内容
|
* --${bound}--
|
* <p>
|
* 其中${bound}是之前头信息中的分隔符,如果头信息中规定是123,那这里也要是123;
|
* 可以很容易看到,这个请求提是多个相同部分组成的:
|
* 每一部分都是以--加分隔符开始的,然后是该部分内容的描述信息,然后一个回车换行,然后是描述信息的具体内容;
|
* 如果传送的内容是一个文件的话,那么还会包含文件名信息以及文件内容类型。
|
* 上面第二部分是一个文件体的结构,最后以--分隔符--结尾,表示请求体结束
|
*
|
* @param urlStr 请求的url
|
* @param filePathMap key 参数名,value 文件的路径
|
* @param keyValues 普通参数的键值对
|
* @param headers
|
* @return
|
* @throws IOException
|
*/
|
public static HttpResponse postFormData(String urlStr, Map<String, String> filePathMap, Map<String, Object> keyValues, Map<String, Object> 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<String, Object> entry : keyValues.entrySet()) {
|
writeSimpleFormField(boundary, out, entry);
|
}
|
}
|
//发送文件类型参数
|
if (filePathMap != null && !filePathMap.isEmpty()) {
|
for (Map.Entry<String, String> 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<String, MultipartFile> filePathMap, Map<String, Object> 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<String, Object> entry : keyValues.entrySet()) {
|
writeSimpleFormField(boundary, out, entry);
|
}
|
}
|
//发送文件类型参数
|
if (filePathMap != null && !filePathMap.isEmpty()) {
|
for (Map.Entry<String, MultipartFile> 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<String, Object> 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<String, Object> 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<String, Object> 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<String, String> textMap,
|
Map<String, String> 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;
|
}
|
|
}
|