当前位置: 代码迷 >> Android >> Android开发之网络请求通讯专题(二):基于HttpClient的文件上传下载
  详细解决方案

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

热度:74   发布时间:2016-04-28 02:37:00.0
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访问的文章已经讲解完毕,希望能够帮助到看到此文的人。







  相关解决方案