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访问的文章已经讲解完毕,希望能够帮助到看到此文的人。







郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。