本文内容如有错误、不足之处,欢迎技术爱好者们一同探讨,在本文下面讨论区留言,感谢。欢迎转载,转载请注明出处(https://blog.csdn.net/feng_xiaoshi/article/details/106083621),谢谢。
简介
通常的POST请求的业务场景,不是上传文件,就是提交表单,很少遇到上传文件同时需要提交表单信息。
Request 信息
本文主要就是解决这个问题,下面是 Jmeter 在测试时,Request 信息:
POST http://localhost/post/fileAndParams
POST data:
--O3UEgNYE7QvWW8f30_NeKK8s436bFmfnhg5j
Content-Disposition: form-data; name="param1"
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
value1
--O3UEgNYE7QvWW8f30_NeKK8s436bFmfnhg5j
Content-Disposition: form-data; name="param2"
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
value2
--O3UEgNYE7QvWW8f30_NeKK8s436bFmfnhg5j
Content-Disposition: form-data; name="file"; filename="text.txt"
Content-Type: application/vnd.ms-execl
Content-Transfer-Encoding: binary
<actual file content, not shown here>
--O3UEgNYE7QvWW8f30_NeKK8s436bFmfnhg5j--
[no cookies]
使用 Java 的 HttpURLConnection 编码
根据上面的 Request 信息,结合Java 的 HttpURLConnection 编写出下面的请求方法。
/**
* POST 请求
* @param requestUrl 请求url
* @param inputStream 输入流
* @param fileName 文件名
* @param params 参数集合
*/
public static String postInputStream(String requestUrl,InputStream inputStream, String fileName,
List<NameValuePair> params) throws IOException {
URL url = new URL(requestUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
try {
// 上面 Jmeter 请求中携带的信息,可以自定义任意字符串
String boundary = "O3UEgNYE7QvWW8f30_NeKK8s436bFmfnhg5j";
// enter功能
String enter = "\r\n";
// 连接做输入、输出
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setRequestMethod("POST");
conn.setUseCaches(false);
conn.setInstanceFollowRedirects(true);
// 模拟数据类型 不要忘记添加 boundary 这里的 boundary 类似于 序列化中的 serialVersionUID
// 但是作用却是连接开始和结束的标识
conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
conn.connect();
// 数据输出流,从服务器输出到网络端
DataOutputStream dos = new DataOutputStream(conn.getOutputStream());
// 组合发送数据格式,模拟 Jmeter
String fileString = "--" + boundary + enter + "Content-Type: application/octet-stream" + enter
+ "Content-Disposition: form-data; name=\"file\"" + "; filename= \"" + fileName + "\"" + enter
+ enter;
// 写入数据流
dos.writeBytes(fileString);
byte[] b = new byte[1024];
int len = 0;
while ((len = inputStream.read(b, 0, 1024)) != -1) {
dos.write(b, 0, len);
}
// 循环放置参数信息
for (NameValuePair param : params) {
String part = enter + "--" + boundary + enter + "Content-Type: text/plain" + enter
+ "Content-Disposition: form-data; name=\"" + param.getName() + "\"" + enter + enter
+ param.getValue() + enter;
dos.writeBytes(part);
}
// 结束
String end = "--" + boundary + "--";
dos.writeBytes(end);
// 刷新流
dos.flush();
dos.close();
// 得到响应流
InputStream responseStream = conn.getInputStream();
// 获取响应
BufferedReader reader = new BufferedReader(new InputStreamReader(responseStream));
String line;
StringBuilder message = new StringBuilder();
while ((line = reader.readLine()) != null) {
message.append(line);
}
// 获取返回信息
return message.toString();
} finally {
inputStream.close();
conn.disconnect();
}
}
通过代码上的注释,结合 Jmeter Request 信息,相信能够很容易理解代码逻辑。
上面的代码是通过 HttpURLConnection 进行的直连,技术深度不高,代码理解需要借助 Jmeter Request 信息。
使用 apache 的 HttpPost 编码
下面是 Post 的进化版
public static String postInputStream(String requestUrl,InputStream inputStream, String fileName,
List<NameValuePair> params) throws IOException {
try (inputStream;CloseableHttpClient httpClient = HttpClients.createDefault();){
// 创建 POST请求
HttpPost httpPost = new HttpPost(requestUrl);
// 构建多组件 Entrity构建器
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setCharset(Charsets.UTF_8);
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
//文件传输http请求头(multipart/form-data)
builder.addBinaryBody("file", inputStream, ContentType.MULTIPART_FORM_DATA, fileName);// 文件流
//字节传输http请求头(application/json)
ContentType contentType = ContentType.create("application/json", Charsets.UTF_8);
for (NameValuePair param : params) {
// 传输字节流
builder.addTextBody(param.getName(), param.getValue(), contentType);
}
HttpEntity entity = builder.build();
httpPost.setEntity(entity);
HttpResponse response = httpClient.execute(httpPost);
// 执行提交
HttpEntity responseEntity = response.getEntity();
if (responseEntity != null) {
// 将响应内容转换为字符串
return EntityUtils.toString(responseEntity, Charsets.UTF_8);
}
} catch (Exception e) {
throw new BusinessException("post请求失败,"+e.getMessage());
}
}