Android開發之網絡請求通信專題(二):基於HttpClient的文件上傳下載

上一篇專題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 block
			e.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
	 */
	@Override
	public 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")
	@Override
	protected 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;
		}
	}

	@Override
	protected void onProgressUpdate(Integer... values) {

		super.onProgressUpdate(values);
	}

	@Override
	protected void onPreExecute() {
		super.onPreExecute();
	}

	@Override
	protected 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() {
				@Override
				public void action(int code, Object obj) {
					//根據返回code判斷執行方法
				}
			}).execute();
		}

好了,第二篇關於http訪問的文章已經講解完畢,希望能夠幫助到看到此文的人。







發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章