標籤:android下http通訊 httpclient使用 android檔案上傳 android檔案下載 android網路訪問
上一篇專題Android開發之網路請求通訊專題(一):基於HttpURLConnection的請求通訊我們講解了如何使用httpurlconnection來實現基本的文本資料轉送。一般在實際開發中我們可以用於傳輸xml或者json格式的資料。今天我們來講解另外一種http網路請求的方式:httpclient,並實現檔案的上傳和下載。
在這裡插個題外話,其實這些網路請求有很多第三方jar包可以使用,這些包都封裝得很好了。如果只是想使用,我們就直接拿別人得jar包來用就好。博主這裡推薦一個叫xutils的工具類,這個玩意其實好用,相信很多人都知道,這個工具類是博主的一個同學的同事寫的。後續博主還會寫一個圖片專題中,也會講解到xutils裡面的圖片類的實現原理。好了,進入今天的正題。
和上一篇專題一樣,我們先講解兩種請求方式的基本用法,然後再深入進行封裝使用。
一、基於httpclient實現檔案的上傳我們先看看最基本的上傳代碼
1、Android端的檔案上傳
/** * @Title: updateFile * @Description: 檔案上傳 * @throws */private void updateFile() {//建立一個httpclient類HttpClient httpclient = new DefaultHttpClient();//用post方式實現檔案上傳HttpPost post = new HttpPost("http://192.168.1.107:10010/MINATest/servlet/UploadServlet");//拿到上傳的圖片String filePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/justice.jpg";//處理上傳的檔案FileBody fileBody = new FileBody(new File(filePath));StringBody stringBody = null;try {stringBody = new StringBody("檔案的描述");} catch (UnsupportedEncodingException e) {// TODO Auto-generated catch blocke.printStackTrace();}MultipartEntity entity = new MultipartEntity();entity.addPart("file", fileBody);entity.addPart("desc", stringBody);post.setEntity(entity);HttpResponse response = null;try {response = httpclient.execute(post);} catch (ClientProtocolException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}if (HttpStatus.SC_OK == response.getStatusLine().getStatusCode()) {//拿到返回的實體,一般而言,用post請求方式返回的流是用這個實體拿到,在這裡不需要所以博主就不寫了。HttpEntity entitys = response.getEntity();if (entity != null) {System.out.println(entity.getContentLength());try {System.out.println(EntityUtils.toString(entitys));} catch (ParseException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}}httpclient.getConnectionManager().shutdown();}
2、服務端dopost處理
/** * * @param request * the request send by the client to the server * @param response * the response send by the server to the client * @throws ServletException * if an error occurred * @throws IOException * if an error occurred */@Overridepublic void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {boolean isMulti = ServletFileUpload.isMultipartContent(request);if (isMulti) {String realPath = request.getSession().getServletContext().getRealPath("/vioce");System.out.println(realPath);File dir = new File(realPath);if (!dir.exists()) {dir.mkdirs();}FileItemFactory factory = new DiskFileItemFactory();ServletFileUpload upload = new ServletFileUpload(factory);upload.setHeaderEncoding("UTF-8");String fileName = null;try {List<FileItem> items = upload.parseRequest(request);for (FileItem item : items) {if (item.isFormField()) {String name = item.getFieldName();String value = item.getString("UTF-8");System.out.println(name + "-" + value);} else {item.write(new File(dir, item.getName()));fileName = item.getName();}}response.setContentType("text/*;charset=utf-8");response.getWriter().write("上傳成功");} catch (Exception e) {e.printStackTrace();}}}我們可以看到當執行了上傳方法之後,在服務端指定的檔案夾中已經有了從android端上傳過來的圖片,而android端的logcat中也列印出了服務端返回的上傳成功的字樣。
3、Android端檔案的下載這裡博主省事了,直接將地址寫死。
/** * @Title: downLoadFile * @Description:檔案下載 * @throws */private void downLoadFile() {HttpClient httpClient1 = new DefaultHttpClient();HttpGet httpGet1 = new HttpGet("http://192.168.31.144:10010/MINATest/vioce/strikefreedom.jpg");try {HttpResponse httpResponse1 = httpClient1.execute(httpGet1);StatusLine statusLine = httpResponse1.getStatusLine();if (statusLine.getStatusCode() == 200) {String filePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/freedom.jpg"; // 檔案路徑File file = new File(filePath);FileOutputStream outputStream = new FileOutputStream(file);InputStream inputStream = httpResponse1.getEntity().getContent();byte b[] = new byte[1024];int j = 0;while ((j = inputStream.read(b)) != -1) {outputStream.write(b, 0, j);}outputStream.flush();outputStream.close();}} catch (Exception e) {e.printStackTrace();} finally {httpClient1.getConnectionManager().shutdown();}}
二、httpclient類的封裝1、封裝邏輯雖然HttPclient相對於httpurlconnection已經有了一定的封裝,api也相對簡潔一些,但是我們還是可以再這個基礎上再進行一次封裝。封裝結構和上一篇差不多。上一篇專題中,我們用了四個類去封裝。這裡我們用android裡的AsyncTask類來替代handler,也可以省去一個回調的監聽。這裡回調介面的設計其實根據需求自己去設定就好,博主就拿之前的一個回調介面來用。這次我們需要三個類
1、http訪問管理者2、任務AsyncTask類3、http訪問結果事件處理回調介面。整個邏輯關係為:http訪問管理者採用get或者post請求方式請求,當產生結果後監聽器告訴訊息通訊管理者應該發送什麼訊息給UI線程,UI線程更具訊息通訊管理者發送過來的訊息,調用對應的事件處理回調介面。
·
接下來我們來一一對應這三個類的編寫
2、http訪問管理者
package com.example.nettest;import java.io.IOException;import java.io.InputStream;import java.io.UnsupportedEncodingException;import java.util.ArrayList;import java.util.List;import org.apache.commons.lang.StringUtils;import org.apache.http.HttpHost;import org.apache.http.HttpRequest;import org.apache.http.HttpResponse;import org.apache.http.NameValuePair;import org.apache.http.client.CookieStore;import org.apache.http.client.entity.UrlEncodedFormEntity;import org.apache.http.client.methods.HttpGet;import org.apache.http.client.methods.HttpPost;import org.apache.http.conn.params.ConnRoutePNames;import org.apache.http.entity.ByteArrayEntity;import org.apache.http.entity.StringEntity;import org.apache.http.impl.client.DefaultHttpClient;import org.apache.http.message.BasicNameValuePair;import org.apache.http.params.BasicHttpParams;import org.apache.http.params.HttpConnectionParams;import org.apache.http.params.HttpParams;import com.lidroid.xutils.http.client.multipart.MultipartEntity;/** * @ClassName: FreedomHttpClientUtil * @author victor_freedom ([email protected]) * @createddate 2015-1-25 下午11:04:59 * @Description: */public class FreedomHttpClientUtil {private DefaultHttpClient client;/** 請求介面 */private HttpRequest httpRequest;/** 響應介面 */private HttpResponse response;/** 方法 */private String mMethod;public static final String POST = "post";public static final String GET = "get";private static final String TAG = "FreedomHttpClientUtil";public static final int HTTP_OK = 200;private void open() {HttpParams params = new BasicHttpParams();HttpConnectionParams.setConnectionTimeout(params, 5000); // 設定連線逾時HttpConnectionParams.setSoTimeout(params, 5000); // 佈建要求逾時client = new DefaultHttpClient(params);try {// 如果不是wifi,我們需要設定一下手機的APN參數if (StringUtils.isNotBlank(ConfigParams.PROXY)) {HttpHost proxy = new HttpHost(ConfigParams.PROXY,ConfigParams.PORT);client.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY,proxy);}// 預設使用UTF-8編碼httpRequest.setHeader("Charset", "UTF-8");} catch (Exception e) {throw new FreedomException(FreedomException.NETWORK_ANOMALY);}}/** * 可以同時處理post與get兩種形式請求 * * @param url * @param method */public void open(String url, String method) {if (StringUtils.isNotBlank(method) && StringUtils.isNotBlank(url)) {if (method.equals(POST)) {httpRequest = new HttpPost(url);mMethod = POST;} else {httpRequest = new HttpGet(url);mMethod = GET;}open();}}/** * @Title: setHttpPostHeader * @Description: 佈建要求頭 * @param name * @param value * @throws */public void setHttpPostHeader(String name, String value) {if (httpRequest == null) {throw new FreedomException(FreedomException.NETWORK_ANOMALY);}if (StringUtils.isNotBlank(name)) {httpRequest.setHeader(name, value);}}/** * @Title: setContent * @Description:設定位元組類型實體 * @param info * @throws */public void setContent(byte[] info) {if (httpRequest == null) {throw new FreedomException(FreedomException.NETWORK_ANOMALY);}if (info.length > 0) {ByteArrayEntity entity = new ByteArrayEntity(info);if (httpRequest instanceof HttpPost)((HttpPost) httpRequest).setEntity(entity);}}/** * @Title: setStringEntity * @Description: 設定字串型實體 * @param datas * @throws */public void setStringEntity(String datas) {if (httpRequest == null) {throw new FreedomException(FreedomException.NETWORK_ANOMALY);}if (null != datas) {try {StringEntity entity = new StringEntity(datas);if (httpRequest instanceof HttpPost)((HttpPost) httpRequest).setEntity(entity);} catch (UnsupportedEncodingException e) {e.printStackTrace();}}}/** * @Title: setJsonStringEntity * @Description: 設定json資料格式實體 * @param datas * @throws */public void setJsonStringEntity(String datas) {if (httpRequest == null) {throw new FreedomException(FreedomException.NETWORK_ANOMALY);}if (null != datas) {try {StringEntity entity = new StringEntity(datas, "utf-8");entity.setContentType("application/json");// entity.setContentEncoding("utf-8");if (httpRequest instanceof HttpPost)((HttpPost) httpRequest).setEntity(entity);} catch (UnsupportedEncodingException e) {e.printStackTrace();}}}/** * @Title: setEntitys * @Description: 設定多參數實體 * @param datas * @throws */public void setEntitys(String... datas) {if (httpRequest == null) {throw new FreedomException(FreedomException.NETWORK_ANOMALY);}if (datas.length > 0) {List<NameValuePair> Parameters = new ArrayList<NameValuePair>();for (int i = 0; i < datas.length; i += 2) {Parameters.add(new BasicNameValuePair(datas[i], datas[i + 1]));}if (httpRequest instanceof HttpPost)try {((HttpPost) httpRequest).setEntity(new UrlEncodedFormEntity(Parameters,"UTF-8"));} catch (UnsupportedEncodingException e) {e.printStackTrace();}}}/** * @Title: setDataEntitys * @Description: 設定資料實體 * @param mpEntity * @throws */public void setDataEntitys(MultipartEntity mpEntity) {if (httpRequest == null) {throw new FreedomException(FreedomException.NETWORK_ANOMALY);}if (httpRequest instanceof HttpPost) {((HttpPost) httpRequest).setEntity(mpEntity);}}/** * @Title: post * @Description: 發送請求 * @throws Exception * @throws */public void post() throws Exception {if (httpRequest == null) {throw new FreedomException(FreedomException.NETWORK_ANOMALY);}if (mMethod.equals(POST)) {response = client.execute((HttpPost) httpRequest);} else {response = client.execute((HttpGet) httpRequest);}}/** * @Title: getContentLength * @Description:拿到返回內容長度 * @return * @throws */public long getContentLength() {long result = 0;if (response == null) {throw new FreedomException(FreedomException.NETWORK_ANOMALY);}result = response.getEntity().getContentLength();return result;}/** * @Title: openInputStream * @Description: 拿到返迴流 * @return * @throws IllegalStateException * @throws IOException * @throws */public InputStream openInputStream() throws IllegalStateException,IOException {if (response == null) {throw new FreedomException(FreedomException.NETWORK_ANOMALY);}InputStream result = response.getEntity().getContent();return result;}/** * @Title: getCookieStore * @Description: 拿到cookie * @return * @throws */public CookieStore getCookieStore() {if (null == client) {throw new FreedomException(FreedomException.NETWORK_ANOMALY);}return client.getCookieStore();}/** * @Title: getResponseCode * @Description:拿到返回碼 * @return * @throws */public int getResponseCode() {int result;if (response == null) {throw new FreedomException(FreedomException.NETWORK_ANOMALY);}result = response.getStatusLine().getStatusCode();return result;}/** * @Title: setRequestProperty * @Description: 佈建要求頭 * @param name * @param value * @throws */public void setRequestProperty(String name, String value) {setHttpPostHeader(name, value);}/** * @ClassName: ConfigParams * @author victor_freedom ([email protected]) * @createddate 2015-1-25 下午11:11:05 * @Description:如果不是WIFI訪問,需要設定的參數 */public static class ConfigParams {public static String SRC = "";public static String PROXY = "";public static int PORT;public static String TYPE = "";public static String MNC = "";}}2、任務AsyncTask類這類的編寫,需要根據實際的業務需求來設定三個參數,相信瞭解AsyncTask類的同學都清楚如何使用這個類。不瞭解的同學也可以百度一下,網上有很多相關的文章。這裡我們以下載檔案的例子來說明
package com.example.nettest;import java.io.File;import java.io.FileOutputStream;import java.io.InputStream;import android.annotation.SuppressLint;import android.app.ProgressDialog;import android.content.Context;import android.os.AsyncTask;import android.os.Environment;/** * @ClassName: FreedomAsynTask * @author victor_freedom ([email protected]) * @createddate 2014年10月12日 下午10:07:36 * @Description: TODO * */public class FreedomAsynTask extends AsyncTask<Void, Integer, String> {private FreedomHttpCallBackListener listener;public FreedomAsynTask(FreedomHttpCallBackListener listener,Context context, ProgressDialog mDialog, String path) {this.listener = listener;}@SuppressLint("DefaultLocale")@Overrideprotected String doInBackground(Void... params) {InputStream is = null;FreedomHttpClientUtil http = new FreedomHttpClientUtil();http.open("http://192.168.31.144:10010/MINATest/vioce/strikefreedom.jpg",FreedomHttpClientUtil.GET);try {http.post();if (http.getResponseCode() == 200) {String filePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/freedom.jpg"; // 檔案路徑File file = new File(filePath);FileOutputStream outputStream = new FileOutputStream(file);InputStream inputStream = http.openInputStream();byte b[] = new byte[1024];int j = 0;while ((j = inputStream.read(b)) != -1) {outputStream.write(b, 0, j);}outputStream.flush();outputStream.close();return "下載成功";} else {return null;}} catch (Exception e) {e.printStackTrace();return null;}}@Overrideprotected void onProgressUpdate(Integer... values) {super.onProgressUpdate(values);}@Overrideprotected void onPreExecute() {super.onPreExecute();}@Overrideprotected void onPostExecute(String result) {if (null != result) {listener.action(FreedomHttpCallBackListener.EVENT_GET_DATA_SUCCESS,result);} else {listener.action(FreedomHttpCallBackListener.EVENT_GET_DATA_EEEOR,null);}super.onPostExecute(result);}}我們可以看到,在不同的返回結果裡面,action裡對應傳入了不同的參數。這裡的監聽封裝博主就偷懶了,直接這麼寫,想要更完善完美一點其實應該可以做的更好。有興趣的同學可以去完善,博主就偷懶了。關於監聽類上一篇文章已經講過,這裡就不在詳細描述我們來看activity中的使用
3、Activity中的使用使用起來非常的簡單,我們只需要一行代碼就實現了檔案的下載
if (NetUtils.checkNetWork(mContext)) {new FreedomAsynTask(new FreedomHttpCallBackListener() {@Overridepublic void action(int code, Object obj) {//根據返回code判斷執行方法}}).execute();}
好了,第二篇關於http訪問的文章已經講解完畢,希望能夠協助到看到此文的人。
Android開發之網路請求通訊專題(二):基於HttpClient的檔案上傳下載