报文格式几个要点说明
multipart/form-data请求主要用来提交媒体内容,也就是提交文件到服务端。multipart表示可以一次提交多个文件,每个文件在报文体中的一段。那么每段的开始结束就要有个约定来标识。body段分为body段头和段体两部分。 约定如下
每段约定格式
\r\n
--i-am-boundary \r\n //说明这是段开始标识
Content-Disposition:name=file1;filename=aa.txt \r\n //说明 这是段头
Content-Type: plain/text \r\n //说明 这是段头
\r\n //段头段体中空行
我是form表单提交的name=file1文件名为aa.txt的文件内容 \r\n //这是段体
--i-am-boundary \r\n
Content-Disposition:name=file2;filename=bb.txt \r\n
Content-Type: plain/text \r\n
\r\n
我是form表单提交的name=file2文件名为vv.txt的文件内容 \r\n
--i-am-boundary-- \r\n
为了编码说明我用【\r\n】表示这是一个换行
- 报文头headers Content-Type设置成如下
Content-Type:multipart/form-data;boundary=i-am-boundary
i-am-boundary为分割线,分割报文body的内容用的,boundary值可以随机生成比如用uuid,
- 报文body段说明
【--i-am-boundary】为每段开始标识,前边加--
【--i-am-boundary--】为报文body结束标识,前后加--
【Content-Disposition,Content-Type】为body段的头部说明, 段头与段体之间留一个空行
代码如下
//--定义几个参数
private static int connectTimeout=1000*60*10; //超时时间
private static int readTimeout=1000*60*10;
private static final String BOUNDARY = "SDIKitFormBoundary"
+UUID.randomUUID().toString().replaceAll("-","").substring(0,16) ; //定义BOUNDARY
private static final String PRE_FIX = ("\r\n--" + BOUNDARY + "\r\n"); //定义开始
private static final String END_FIX = ("\r\n--" + BOUNDARY + "--\r\n"); //定义结束
//--此为发送文件方法
public static String postFile(String urlStr, String accept, byte[] fileContent, String fileFormName, String fileName, HashMap<String,String> postParam, HashMap<String,String> headersParam){
HttpURLConnection con = null;
DataOutputStream outputStream=null;
// BufferedReader buffer = null;
//StringBuffer resultBuffer = null;
try {
URL url = new URL(urlStr);
//得到连接对象
con = (HttpURLConnection) url.openConnection();
con.setConnectTimeout(connectTimeout);
con.setReadTimeout(readTimeout);
con.setRequestMethod("POST");
//设置请求需要返回的数据类型和字符集类型
con.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + BOUNDARY);
con.setRequestProperty("connection", "keep-alive");
con.setRequestProperty("Accept",accept);
//允许写出
con.setDoOutput(true);
//允许读入
con.setDoInput(true);
//不使用缓存
con.setUseCaches(false);
//----构建headers
if(headersParam!=null&&!headersParam.keySet().isEmpty()){
for(String key : headersParam.keySet()){
con.setRequestProperty(key, headersParam.getOrDefault(key,""));
}
}
//----构建file数据
outputStream = new DataOutputStream(con.getOutputStream());
// 要上传的数据
StringBuffer strBuf = new StringBuffer();
// 标识payLoad + 文件流的起始位置
strBuf.append(PRE_FIX);
strBuf.append("Content-Disposition: form-data; name=""+fileFormName+""; filename="" + fileName+ ""\r\n");
strBuf.append("Content-Type: application/octet-stream" + "\r\n");
strBuf.append("\r\n"); //留一个空行
outputStream.write(strBuf.toString().getBytes());
outputStream.write(fileContent);
//二构建其他参数
if(postParam!=null&&!postParam.keySet().isEmpty()){
StringBuilder contentBody = new StringBuilder();
for(String key : postParam.keySet()){
contentBody.append(PRE_FIX);
contentBody.append("Content-Disposition: form-data; name=""+key+""\r\n");
contentBody.append("\r\n"); //参数换行
contentBody.append(postParam.getOrDefault(key,"")); //参数值
}
outputStream.write(contentBody.toString().getBytes());
}
//结束
outputStream.write(END_FIX.getBytes());
outputStream.flush();
con.connect();
int responseCode=con.getResponseCode();
// con.getHeaderFields()
if (responseCode == 200) {
// 获取返回流
return getResult(con.getInputStream());
}else {
//此处判断一下500
String str=getResult(con.getErrorStream());
throw new RuntimeException( String.valueOf(responseCode)+":"+str);
}
} catch (Exception e) {
// e.printStackTrace();
throw new RuntimeException("http请求出错 \r\n"+e.getMessage());
}
}
//此处Stream转字符串
public static String getResult(InputStream inputStream) {
String result = "";
ByteArrayOutputStream dataOutputStream = null;
try {
byte[] buf = new byte[1024];
int n;
dataOutputStream = new ByteArrayOutputStream();
while (((n = inputStream.read(buf)) != -1)) {
dataOutputStream.write(buf, 0, n);
}
result = new String(dataOutputStream.toByteArray(), "UTF-8");
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException("获取httpResponse出错 \r\n"+e.getMessage());
}finally {
try {
if(inputStream!=null) inputStream.close();
if(dataOutputStream!=null) dataOutputStream.close();
} catch (IOException e) {
}
}
return result;
}