Android 發送HTTP GET POST 請求以及通過 MultipartEntityBuilder 上傳文件
折騰了好幾天的 HTTP 終於搞定了,經測試正常,不過是初步用例測試用的,因為後麵還要修改先把當前版本保存在博客裏吧。
其中POST因為涉及多段上傳需要導入兩個包文件,我用的是最新的 httpmine4.3 發現網上很多 MultipartEntity 相關的文章都是早起版本的,以前的一些方法雖然還可用,但新版本中已經不建議使用了,所以全部使用新的方式 MultipartEntityBuilder 來處理了。
httpmime-4.3.2.jar httpcore-4.3.1.jar
下載地址:https://hc.apache.org/downloads.cgi
有些鏡像貌似打不開,頁麵上可以可以選擇國內的 .cn 後綴的域名鏡像服務器來下載
如果是 android studio 這裏可能會遇到一個問題:Android Duplicate files copied in APK
經測試 POST 對中文處理也是正常的,沒有發現亂碼
下麵是完整代碼:
ZHttpRequest.java
package com.ai9475.util; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpRequestBase; import org.apache.http.entity.ContentType; import org.apache.http.entity.mime.HttpMultipartMode; import org.apache.http.entity.mime.MultipartEntityBuilder; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.params.BasicHttpParams; import org.apache.http.params.HttpConnectionParams; import org.apache.http.params.HttpParams; import org.apache.http.protocol.HTTP; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.nio.charset.Charset; import java.util.Iterator; import java.util.Map; import java.util.Set; /** * Created by ZHOUZ on 14-2-3. */ public class ZHttpRequest { protected String url = ""; protected Map<String, String> headers = null; protected int connectionTimeout = 5000; protected int soTimeout = 10000; protected int statusCode = 200; protected String charset = HTTP.UTF_8; protected HttpGet httpGet; protected HttpPost httpPost; protected HttpParams httpParameters; protected HttpResponse httpResponse; protected HttpClient httpClient; protected String inputContent; /** * 設置當前請求的鏈接 * * @param url * @return */ public ZHttpRequest setUrl(String url) { this.url = url; return this; } /** * 設置請求的 header 信息 * * @param headers * @return */ public ZHttpRequest setHeaders(Map headers) { this.headers = headers; return this; } /** * 設置連接超時時間 * * @param timeout 單位(毫秒),默認 5000 * @return */ public ZHttpRequest setConnectionTimeout(int timeout) { this.connectionTimeout = timeout; return this; } /** * 設置 socket 讀取超時時間 * * @param timeout 單位(毫秒),默認 10000 * @return */ public ZHttpRequest setSoTimeout(int timeout) { this.soTimeout = timeout; return this; } /** * 設置獲取內容的編碼格式 * * @param charset 默認為 UTF-8 * @return */ public ZHttpRequest setCharset(String charset) { this.charset = charset; return this; } /** * 獲取 HTTP 請求響應信息 * * @return */ public HttpResponse getHttpResponse() { return this.httpResponse; } /** * 獲取 HTTP 客戶端連接管理器 * * @return */ public HttpClient getHttpClient() { return this.httpClient; } /** * 獲取請求的狀態碼 * * @return */ public int getStatusCode() { return this.statusCode; } /** * 通過 GET 方式請求數據 * * @param url * @return * @throws IOException */ public String get(String url) throws IOException { // 設置當前請求的鏈接 this.setUrl(url); // 實例化 GET 連接 this.httpGet = new HttpGet(this.url); // 自定義配置 header 信息 this.addHeaders(this.httpGet); // 初始化客戶端請求 this.initHttpClient(); // 發送 HTTP 請求 this.httpResponse = this.httpClient.execute(this.httpGet); // 讀取遠程數據 this.getInputStream(); // 遠程請求狀態碼是否正常 if (this.statusCode != HttpStatus.SC_OK) { return null; } // 返回全部讀取到的字符串 return this.inputContent; } public String post(String url, Map<String, String> datas, Map<String, String> files) throws IOException { this.setUrl(url); // 實例化 GET 連接 this.httpPost = new HttpPost(this.url); // 自定義配置 header 信息 this.addHeaders(this.httpPost); // 初始化客戶端請求 this.initHttpClient(); Iterator iterator = datas.entrySet().iterator(); MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create(); multipartEntityBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE); multipartEntityBuilder.setCharset(Charset.forName(this.charset)); // 發送的數據 while (iterator.hasNext()) { Map.Entry<String, String> entry = (Map.Entry<String, String>) iterator.next(); multipartEntityBuilder.addTextBody(entry.getKey(), entry.getValue(), ContentType.create("text/plain", Charset.forName(this.charset))); } // 發送的文件 if (files != null) { iterator = files.entrySet().iterator(); while (iterator.hasNext()) { Map.Entry<String, String> entry = (Map.Entry<String, String>) iterator.next(); String path = entry.getValue(); if ("".equals(path) || path == null) continue; File file = new File(entry.getValue()); multipartEntityBuilder.addBinaryBody(entry.getKey(), file); } } // 生成 HTTP 實體 HttpEntity httpEntity = multipartEntityBuilder.build(); // 設置 POST 請求的實體部分 this.httpPost.setEntity(httpEntity); // 發送 HTTP 請求 this.httpResponse = this.httpClient.execute(this.httpPost); // 讀取遠程數據 this.getInputStream(); // 遠程請求狀態碼是否正常 if (this.statusCode != HttpStatus.SC_OK) { return null; } // 返回全部讀取到的字符串 return this.inputContent.toString(); } /** * 為 HTTP 請求添加 header 信息 * * @param request */ protected void addHeaders(HttpRequestBase request) { if (this.headers != null) { Set keys = this.headers.entrySet(); Iterator iterator = keys.iterator(); Map.Entry<String, String> entry; while (iterator.hasNext()) { entry = (Map.Entry<String, String>) iterator.next(); request.addHeader(entry.getKey().toString(), entry.getValue().toString()); } } } /** * 配置請求參數 */ protected void setParams() { this.httpParameters = new BasicHttpParams(); this.httpParameters.setParameter("charset", this.charset); // 設置 連接請求超時時間 HttpConnectionParams.setConnectionTimeout(this.httpParameters, this.connectionTimeout); // 設置 socket 讀取超時時間 HttpConnectionParams.setSoTimeout(this.httpParameters, this.soTimeout); } /** * 初始化配置客戶端請求 */ protected void initHttpClient() { // 配置 HTTP 請求參數 this.setParams(); // 開啟一個客戶端 HTTP 請求 this.httpClient = new DefaultHttpClient(this.httpParameters); } /** * 讀取遠程數據 * * @throws IOException */ protected void getInputStream() throws IOException { // 接收遠程輸入流 InputStream inStream = this.httpResponse.getEntity().getContent(); // 分段讀取輸入流數據 ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] buf = new byte[1024]; int len = -1; while ((len = inStream.read(buf)) != -1) { baos.write(buf, 0, len); } // 將數據轉換為字符串保存 this.inputContent = new String(baos.toByteArray()); // 數據接收完畢退出 inStream.close(); // 獲取請求返回的狀態碼 this.statusCode = this.httpResponse.getStatusLine().getStatusCode(); } /** * 關閉連接管理器釋放資源 */ protected void shutdownHttpClient() { if (this.httpClient != null && this.httpClient.getConnectionManager() != null) { this.httpClient.getConnectionManager().shutdown(); } } }
MainActivity.java
這個我就隻寫事件部分了
public void doClick(View view) { ZHttpRequest request = new ZHttpRequest(); String url = ""; TextView textView = (TextView) findViewById(R.id.showContent); String content = "空內容"; try { if (view.getId() == R.id.doGet) { url = "https://www.baidu.com"; content = "GET數據:" + request.get(url); } else { url = "https://192.168.1.6/test.php"; HashMap<String, String> datas = new HashMap<String, String>(); datas.put("p1", "abc"); datas.put("p2", "中文"); datas.put("p3", "abc中文cba"); datas.put("pic", this.picPath); HashMap<String, String> files = new HashMap<String, String>(); files.put("file", this.picPath); content = "POST數據:" + request.post(url, datas, files); } } catch (IOException e) { content = "IO異常:" + e.getMessage(); } catch (Exception e) { content = "異常:" + e.getMessage(); } textView.setText(content); }
其中的 this.picPath 就是指定的SD卡中的相片路徑 String 類型
activity_main.xml
<LinearLayout xmlns:andro android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <ScrollView android:layout_width="fill_parent" android:layout_height="fill_parent" > <LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <Button android: android:layout_width="fill_parent" android:layout_height="wrap_content" android:padding="10dp" android:layout_marginBottom="10dp" android:text="GET請求" android:onClick="doClick" /> <Button android: android:layout_width="fill_parent" android:layout_height="wrap_content" android:padding="10dp" android:layout_marginBottom="10dp" android:text="POST請求" android:onClick="doClick" /> <Button android: android:layout_width="fill_parent" android:layout_height="wrap_content" android:padding="10dp" android:layout_marginBottom="10dp" android:text="拍照" android:onClick="doPhoto" /> <ImageView android: android:layout_width="fill_parent" android:layout_height="250dp" android:scaleType="centerCrop" android:src="@drawable/add" android:layout_marginBottom="10dp" /> <TextView android: android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginBottom="10dp" /> </LinearLayout> </ScrollView> </LinearLayout>
由於我現在對Java 還不是很熟悉,隻看過一些視頻教程,實際開發經驗不多,我按自己的理解寫的注釋,不過應該不會有什麼太大問題吧,如有錯誤請指出,謝謝!
最後更新:2017-04-03 12:54:58