Java POST請求發送文件同時發送參數

本文內容如有錯誤、不足之處,歡迎技術愛好者們一同探討,在本文下面討論區留言,感謝。歡迎轉載,轉載請註明出處(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());
        }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章