本文內容如有錯誤、不足之處,歡迎技術愛好者們一同探討,在本文下面討論區留言,感謝。歡迎轉載,轉載請註明出處(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());
}
}