java发送post请求上传文件和json数据
因为第三方的上传服务post参数使用了两个@requestpart参数。
但是feign不可以使用两个@requestpart参数。会报错:java.lang.IllegalStateException: Method has too many Body parameters
所以使用http发送post请求上传文件和json数据。
package com.evisible.blockchain.common.utils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.multipart.MultipartFile;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.text.SimpleDateFormat;
import java.util.*;
@Slf4j
public class HttpRequestUtil {
private final static String BOUNDARY = UUID.randomUUID().toString().toLowerCase().replaceAll("-", "");// 边界标识
private final static String PREFIX = "--";// 必须存在
private final static String LINE_END = "\r\n";
/**
* 发送post请求
* @Description:
* @param requestUrl 请求url
* @param requestText 请求参数
* @param requestFile 请求上传的文件
* @param headers 其他自定义请求头
* @return
* @throws Exception
*/
public static String sendPost(String requestUrl,
Map requestText, Map requestFile, Map headers) throws Exception{
HttpURLConnection conn = null;
InputStream input = null;
OutputStream os = null;
BufferedReader br = null;
StringBuffer buffer = null;
try {
URL url = new URL(requestUrl);
if("https".equalsIgnoreCase(url.getProtocol())){
try {
SslUtils.ignoreSsl();
} catch (Exception e) {
e.printStackTrace();
}
}
conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setUseCaches(false);
conn.setConnectTimeout(1000 * 10);
conn.setReadTimeout(1000 * 10);
conn.setRequestMethod("POST");
conn.setRequestProperty("Accept", "*/*");
conn.setRequestProperty("Connection", "keep-alive");
conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
conn.setRequestProperty("Charset", "UTF-8");
conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY);
//设置其他自定义 headers
if (headers != null && !headers.isEmpty()) {
for (Map.Entry header : headers.entrySet()) {
if( header.getValue()!=null){
conn.setRequestProperty(header.getKey(), header.getValue().toString());
}
}
}
conn.connect();
// 往服务器端写内容 也就是发起http请求需要带的参数
os = new DataOutputStream(conn.getOutputStream());
// 请求参数部分
writeParams(requestText, os);
// 请求上传文件部分
writeFile(requestFile, os);
// 请求结束标志
String endTarget = PREFIX + BOUNDARY + PREFIX + LINE_END;
os.write(endTarget.getBytes());
os.flush();
if(conn.getResponseCode()==200){
input = conn.getInputStream();
}else{
input = conn.getErrorStream();
}
br = new BufferedReader(new InputStreamReader( input, "UTF-8"));
buffer = new StringBuffer();
String line = null;
while ((line = br.readLine()) != null) {
buffer.append(line);
}
//......
System.out.println("返回报文:" + buffer.toString());
} catch (Exception e) {
log.error(e.getMessage(), e);
throw new Exception(e);
} finally {
try {
if (conn != null) {
conn.disconnect();
conn = null;
}
if (os != null) {
os.close();
os = null;
}
if (br != null) {
br.close();
br = null;
}
} catch (IOException ex) {
log.error(ex.getMessage(), ex);
throw new Exception(ex);
}
}
return buffer.toString();
}
/**
* 对post参数进行编码处理并写入数据流中
* @throws Exception
*
* @throws IOException
*
* */
private static void writeParams(Map requestText,
OutputStream os) throws Exception {
try{
if (requestText == null || requestText.isEmpty()) {
} else {
StringBuilder requestParams = new StringBuilder();
Set> set = requestText.entrySet();
Iterator> it = set.iterator();
while (it.hasNext()) {
Map.Entry entry = it.next();
requestParams.append(PREFIX).append(BOUNDARY).append(LINE_END);
requestParams.append("Content-Disposition: form-data; name=\"")
.append(entry.getKey()).append("\"").append(LINE_END);
requestParams.append("Content-Type: text/plain; charset=utf-8")
.append(LINE_END);
requestParams.append("Content-Transfer-Encoding: 8bit").append(
LINE_END);
requestParams.append(LINE_END);// 参数头设置完以后需要两个换行,然后才是参数内容
requestParams.append(entry.getValue());
requestParams.append(LINE_END);
}
os.write(requestParams.toString().getBytes());
os.flush();
}
}catch(Exception e){
log.error("writeParams failed", e);
throw new Exception(e);
}
}
/**
* 对post上传的文件进行编码处理并写入数据流中
*
* @throws IOException
*
* */
private static void writeFile(Map requestFile,
OutputStream os) throws Exception {
InputStream is = null;
try{
String msg = "请求上传文件部分:\n";
if (requestFile == null || requestFile.isEmpty()) {
msg += "空";
} else {
StringBuilder requestParams = new StringBuilder();
Set> set = requestFile.entrySet();
Iterator> it = set.iterator();
while (it.hasNext()) {
Map.Entry entry = it.next();
if(entry.getValue() == null){//剔除value为空的键值对
continue;
}
requestParams.append(PREFIX).append(BOUNDARY).append(LINE_END);
requestParams.append("Content-Disposition: form-data; name=\"")
.append(entry.getKey()).append("\"; filename=\"")
.append(entry.getValue().getName()).append("\"")
.append(LINE_END);
requestParams.append("Content-Type:")
.append(entry.getValue().getContentType())
.append(LINE_END);
requestParams.append("Content-Transfer-Encoding: 8bit").append(
LINE_END);
requestParams.append(LINE_END);// 参数头设置完以后需要两个换行,然后才是参数内容
os.write(requestParams.toString().getBytes());
os.write(entry.getValue().getBytes());
os.write(LINE_END.getBytes());
os.flush();
msg += requestParams.toString();
}
}
//System.out.println(msg);
}catch(Exception e){
log.error("writeFile failed", e);
throw new Exception(e);
}finally{
try{
if(is!=null){
is.close();
}
}catch(Exception e){
log.error("writeFile FileInputStream close failed", e);
throw new Exception(e);
}
}
}
/**
* ContentType(这部分可忽略,MultipartFile有对应的方法获取)
*
* @Description:
* @param file
* @return
* @throws IOException
*/
public static String getContentType(MultipartFile file) throws Exception{
String streamContentType = "application/octet-stream";
String imageContentType = "";
ImageInputStream image = null;
try {
image = ImageIO.createImageInputStream(file);
if (image == null) {
return streamContentType;
}
Iterator it = ImageIO.getImageReaders(image);
if (it.hasNext()) {
imageContentType = "image/" + it.next().getFormatName();
return imageContentType;
}
} catch (IOException e) {
log.error("method getContentType failed", e);
throw new Exception(e);
} finally {
try{
if (image != null) {
image.close();
}
}catch(IOException e){
log.error("ImageInputStream close failed", e);;
throw new Exception(e);
}
}
return streamContentType;
}
}
下面是测试类
//上传并进行签章
public static void main(String[] args) throws Exception {
//请求 url
String url = "https://139.9.57.182/api/cfca-anxin-sign/api/uploadAndSignCustomPDFContract3203";
// keyValues 保存普通参数
Map keyValues = new HashMap<>();
String uploadContract = "{\"isSign\":2,\"contractTypeCode\":\"MM\",\"contractName\":\"测试合同\",\"signKeyword\":{\"keyword\":\"通过见证人\",\"offsetCoordX\":\"0\",\"offsetCoordY\":\"20\",\"imageWidth\":\"150\",\"imageHeight\":\"150\"},\"signLocations\":[{\"signOnPage\":\"1\",\"signLocationLBX\":\"240\",\"signLocationLBY\":\"430\",\"signLocationRUX\":\"340\",\"signLocationRUY\":\"530\"}],\"signInfos\":[{\"userId\":\"35FE921E7CF0F890E050007F01004E8E\",\"authorizationTime\":\"20160214171200\",\"location\":\"210.74.41.0\",\"projectCode\":\"003\",\"isProxySign\":1,\"signLocations\":[{\"signOnPage\":\"1\",\"signLocationLBX\":\"85\",\"signLocationLBY\":\"550\",\"signLocationRUX\":\"140\",\"signLocationRUY\":\"575\"}]}]}";
keyValues.put("uploadContract", uploadContract);
// filePathMap 保存文件类型的参数名和文件路径
Map filePathMap = new HashMap<>();
File file = new File("d://山月记.pdf");
FileInputStream fileInputStream = new FileInputStream(file);
MultipartFile multipartFile = new MockMultipartFile(file.getName(),
file.getName(), ContentType.APPLICATION_OCTET_STREAM.toString(),
fileInputStream);
filePathMap.put("file", multipartFile);
Map header = new HashMap<>();
header.put("Authorization", "Bearer eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1c2VyOjhhYWE4MTkzNmY3ZjI0YWMwMTZmODJmNWJkMjQwMDFhIiwiT05BIjoi6L-Z5piv56ys5LiA5Liq5L-u5pS5IiwiT1IiOiJQTEFURk9STSIsIkxQIjoibGRxeWIiLCJVQVMiOiJCVlcsRklSU1RfQVVESVQsVVBDLFNMQSxVTEEsVUEsVUQsUExBVEZPUk0sQUdSVF9RVUVSWSxVUFIsVUwsQkFOTkVSX01HVCxBU1NFVF9NR1QsRUEsU0VDT05EX0FVRElULGF1dGgtbG9naW4sVVUsQUEsRklOQUxfQVVESVQsQUQsVVNFUl9JTkZPX01HVCxJVEVNX01HVCxBTCxCQ00sSEVBRFFVQVRFUl9BVURJVCxPUkdfSU5GT19NR1QsUkEsUkQsUEFZX01HVCxBVSxQUk9KRUNUX0ZPUkNFX01HVCxSTCxSTSxTTVNfTUdULE9STEEsT1JBLE9SRCxSVSxPUkcsUkxBLE9STCxTQSxVU0VSX01HVCxTRCxPUlUsQkFOS19DQVJEX01HVCxTTCxHTF9NQU5BR0VSLEJJTkRfT1BFUkFUSU9OX1BIT05FLEJVU0lORVNTX01HVCxTVSxBR1JUX01HVCxST0xFX01HVCxVU0MsRElDVF9NR1QsVU9SUlUsVU9SRCxVT1JBLFNPQ19NR1QsQUxBLEJQTU5fTUdULFBNLEFHUlRfU0lHTixsZHF5Yi1sb2dpbiIsImlzcyI6ImV2LWF1dGgiLCJ2cmYiOiJ0cnVlIiwiT0lEIjoiYmE5YjMzZDctN2ExNy00MWI4LTkwYWUtZGE1YmNmODhhMGM2IiwiVUlEIjoiOGFhYTgxOTM2ZjdmMjRhYzAxNmY4MmY1YmQyNDAwMWEiLCJBVCI6Im90IiwidHR5IjoiaWR0IiwiVU4iOiIxNTYyNDk4NDYwMiIsImV4cCI6MTU5MzQ4MTk5OSwiVVQiOiJFTlRFUlBSSVNFIn0.0XLzW7FM6j5zIogzt2-p0pcH_BpFPwrICgPg0h0qnLw");
String response = HttpRequestUtil.sendPost(url, keyValues, filePathMap,header);
System.out.println("response:"+response);
}