1. 程式人生 > >httpclient4.5如何以二進位制流的形式上傳檔案

httpclient4.5如何以二進位制流的形式上傳檔案

本人在做介面測試的過程中,遇到了上傳檔案的測試。由於之前沒有測試過流上傳,導致花費了一些時間,還有就是網上關於httpclient4.5的資料和其他版本資料混在一起,也浪費了一些時間。經過測試終於可用了。暫時沒有進一步封裝,下面分享一些主要的程式碼。其實 httpclient 物件我在一個基礎類中以靜態變數的形式一開始就載入好了,為了減少理解的障礙,我後面會把建立httpclient 的方法也附帶在後面。

public void uploadPic() throws FileNotFoundException {
		HttpPost httppost = new HttpPost(url);
		// 建立二進位制檔案流
		InputStream inputStream = new FileInputStream(file);
		StringBody index = new StringBody("7", ContentType.create("text/plain", Consts.UTF_8));
		// 建立 part contentBody,第一個是值,第二個引數是型別,第三個引數是編碼格式
		// 建立MultipartEntityBuilder物件
		MultipartEntityBuilder builder = MultipartEntityBuilder.create();
		// 新增二進位制檔案流,第一個引數是介面引數名,第二個引數是檔案的二進位制流,第三個引數是檔名
		builder.addBinaryBody("user_pic", inputStream, ContentType.create("multipart/form-data"), "11.png");
		// 新增引數和引數值
		builder.addPart("user_pic_index", index);
		// 建立 httpentity 實體
		HttpEntity httpEntity = builder.build();
		// 設定 httpentity 實體
		httppost.setEntity(httpEntity);
		// 傳送請求獲取相應
		JSONObject response = getHttpResponseEntityByJson(httppost);
		output(response);
	}
其中output 方法在另外一篇文章中寫過了,這裡就不多寫了,只是一個格式化輸出 json 物件的方法。

下面是getHttpResponseEntityByJson方法:

	/**
	 * 獲取響應實體,暫無header設定
	 * 
	 * @param request
	 *            請求物件
	 * @return 返回json型別的物件
	 */
	public JSONObject getHttpResponseEntityByJson(HttpRequestBase request) {
		output(request.getURI());
		JSONObject jsonObject = new JSONObject();
		CloseableHttpResponse response = null;// 建立響應物件
		long data_size = 0;// 用於存放資料大小
		Map<String, String> info = getRequestInfo(request);
		String api_name = info.get("api_name");
		String type = info.get("type");
		String host_name = info.get("host_name");
		String method = info.get("method");
		String uri = info.get("uri");
		String params = info.get("params");
		request.addHeader(HTTP.USER_AGENT, "okhttp/3.9.1");// 符合應用防火牆
		mark = getMark();
		Date start = getDate();// 記錄開始時間
		try {
			response = httpClient.execute(request);
		} catch (ClientProtocolException e1) {
			output("client請求異常", e1);
		} catch (IOException e1) {
			output("執行請求時java IO 異常!", e1);
		} // 獲取響應
		Date end = getDate();// 記錄結束時間
		double elapsed_time = outputTimeDiffer(start, end);// 獲取響應耗時
		int status = response.getStatusLine().getStatusCode();// 獲取響應狀態
		HttpEntity entity = response.getEntity();// 獲取響應實體
		data_size = entity.getContentLength();// 獲取相應資料大小
		if (data_size == -1) {// 如果為-1,則重置data_size
			data_size = 0;
		}
		String content = null;
		try {
			content = EntityUtils.toString(entity, "utf-8");// 用string接收響應實體
			EntityUtils.consume(entity);// 消耗響應實體
		} catch (ParseException e1) {
			output("解析響應實體異常!", e1);
		} catch (IOException e1) {
			output("解析響應實體時java IO 異常!", e1);
		} // 解析響應
		try {
			response.close();
		} catch (IOException e2) {
			output("響應關閉失敗!", e2);
		}
		if (data_size == 0) {// 如果被重置或者沒有獲取到,則data_size等於解析string大小
			try {
				data_size = content.length();
			} catch (Exception e) {
				data_size = 1;
				output("獲取響應長度異常!", e);
			}
		}
		if (status == 200) {
			try {
				jsonObject = JSONObject.fromObject(content);
			} catch (Exception e) {
				output("相應狀態碼錯誤,相應內容:" + content, e);
			}
		} else {
			output("響應內容:" + content);
		}
		// request.releaseConnection();//此處容易造成socket close,在連線池時使用
		MySqlTest.getInstance().saveApiTestDate(host_name, api_name, data_size, elapsed_time, status, type, mark,
				method, uri, params);
		return jsonObject;
	}

中間涉及到獲取資訊getRequestInfo方法如下:
	/**
	 * 封裝獲取請求的各種資訊的方法
	 * 
	 * @param httpRequestBase
	 *            傳入請求物件
	 * @return 返回一個map,包含api_name,host_name,type,method,params
	 */
	public Map<String, String> getRequestInfo(HttpRequestBase request) {
		Map<String, String> info = new HashMap<>();// 新建map儲存資訊
		String method = request.getMethod();// 獲取method
		info.put("method", method);
		String uri = request.getURI().toString();// 獲取uri
		info.put("uri", uri);
		String url = uri;
		if (uri.contains("?")) {// 獲取url,如果是get請求,先擷取
			url = uri.substring(0, uri.indexOf("?"));
		}
		String one = url.substring(url.indexOf("//") + 2);// 刪除掉http://
		String api_name = one.substring(one.indexOf("/"));// 獲取介面名
		info.put("api_name", api_name);
		String host_name = one.substring(0, one.indexOf("/"));// 獲取host地址
		info.put("host_name", host_name);
		String type = url.substring(0, url.indexOf("//") - 1);// 獲取協議型別
		info.put("type", type);
		String params = null;// 引數
		if (method.equals("GET")) {
			params = uri.substring(uri.indexOf("?") + 1, uri.length());
		} else if (method.equals("POST")) {
			HttpPost httpPost = (HttpPost) request;// 強轉httppost請求
			HttpEntity entity = httpPost.getEntity();// 獲取實體
			try {
				params = EntityUtils.toString(entity);// 解析實體
				EntityUtils.consume(entity);// 確保實體消耗
			} catch (ParseException e) {
				output("解析響應實體異常!", e);
			} catch (IOException e) {
				output("解析響應實體時java IO 異常!", e);
			} catch (UnsupportedOperationException e) {
				params = "entity型別:" + entity.getClass();
				output("不被支援的entity 型別!", e);
			}
		}
		info.put("params", params);
		return info;
	}
下面是載入 httpclient 物件的方法:
public static CloseableHttpClient httpClient = getCloseableHttpClients();

	/**
	 * 獲取httpclient物件
	 * 
	 * @return 返回HTTPclient物件
	 */
	public static CloseableHttpClient getCloseableHttpClients() {
		return HttpClients.createDefault();
	}

末了再次宣傳一下自己的 QQ群:群號:340964272。