Android开发之网络请求通信专题(二):基于HttpClient的文件上传下载

来源:互联网 发布:成志网络 编辑:程序博客网 时间:2024/06/05 15:15

上一篇专题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 (x_freedom_reddevil@126.com) * @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 (x_freedom_reddevil@126.com) * @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 (x_freedom_reddevil@126.com) * @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访问的文章已经讲解完毕,希望能够帮助到看到此文的人。







1 1