转载请注明出处,谢谢啦~
项目背景:做项目经常用到http请求,市面上对于http请求的框架也是非常多,不乏一些经典如volley之流。但是我们有时候并不会用到那么大的框架,例如我们不会频繁的且大量的下载图片,不会有oom的顾虑,而且我们要做上传,而不是下载,再而且,我们不需要特别复杂的框架,只需要Android原生的就可以做到需求,那么我们为什么要导入那么大的框架。我们做上传的时候如果需要上传文件,市面上大多数框架又不支持了怎么办?!这个轻量级的封装就是针对这一需求而来。
首先这套工具是基于HttpClient的,我想没有人愿意去拼凑HttpURLConnection那烦躁的请求头,代码导入了httpmime的源码,并非jar包,对源码本着能不修改就不修改的原则,关于上传的进度显示采用了继承复写的方式来提供接口。下面进行简单的讲解。
public NetWork(String url){
Log.d(TAG, "NetWork is started.");
setHttpClient();
post = new HttpPost(url);
}
private void setHttpClient(){
client = new DefaultHttpClient();
client.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, REQUEST_TIMEOUT);
client.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, SO_TIMEOUT);
client.getParams().setParameter(CoreProtocolPNames.HTTP_CONTENT_CHARSET, charSet);
}
这是这个主类的初始化,我们可以看到这是对HttpClient进行了一些初始化操作,包括设置HttpClient 的超时时间,请求时间和编码集的设定。
/**
* If you want to add some headers in your http request,you must use this method before
* {@link #doPost(Map, String, File, boolean, ProgressListener)}doPost.
* @param headersSet The Map you save your header's params.
*/
public void createCommonHeader(Map headersSet) {
headers = new Header[headersSet.size()];
Set> entrySet = headersSet.entrySet();
int i = 0 ;
for (Entry entry : entrySet) {
headers[i] = new BasicHeader(entry.getKey(), entry.getValue());
i += 1;
}
}
这段代码是对请求头的一些设置,这里需要传递进来一个Map集合,集合里包括了所有的请求头,然后遍历封装到header集合里。
public String doPost(Map params,String fileType,File file,boolean hasHeader,ProgressListener listener){
try {
CustomMultiPartEntity multipartCOntent= new CustomMultiPartEntity(listener);
if(params!=null){
Set> entrySet = params.entrySet();
for (Entry entry : entrySet) {
multipartContent.addPart(entry.getKey(), new StringBody(entry.getValue()));
}
}
if (fileType != null && file != null ) {
// We use FileBody to transfer an file
multipartContent.addPart(fileType, new FileBody(file));
}
post.setEntity(multipartContent);
if (hasHeader) {
if (headers != null) {
post.setHeaders(headers);
}
}
HttpResponse respOnse= client.execute(post);
int statusCode = response.getStatusLine().getStatusCode();
Log.v(TAG, "statusCode : " + statusCode);
//Using the same charset to read the response.
String serverRespOnse= EntityUtils.toString(response.getEntity(),charSet);
Log.v(TAG, "serverResponse : " + serverResponse);
if(statusCode!=200){
Log.v(TAG, "serverResponse : " + serverResponse);
return null;
}
return serverResponse;
} catch (Exception e) {
Log.e(TAG, e.getMessage());
return null;
}
}
这是最终的post请求,如果请求成功会返回服务器返回的数据,如果请求失败会返回null,调用时做下判断即可。
public class CustomMultiPartEntity extends MultipartEntity {
private final ProgressListener listener;
public CustomMultiPartEntity(final ProgressListener listener) {
super();
this.listener = listener;
}
public CustomMultiPartEntity(final HttpMultipartMode mode,
final ProgressListener listener) {
super(mode);
this.listener = listener;
}
public CustomMultiPartEntity(HttpMultipartMode mode, final String boundary,
final Charset charset, final ProgressListener listener) {
super(mode, boundary, charset);
this.listener = listener;
}
@Override
public void writeTo(final OutputStream outstream) throws IOException {
super.writeTo(new CountingOutputStream(outstream, this.listener));
}
public static interface ProgressListener {
void transferred(long num);
}
public static class CountingOutputStream extends FilterOutputStream {
private final ProgressListener listener;
private long transferred;
public CountingOutputStream(final OutputStream out,
final ProgressListener listener) {
super(out);
this.listener = listener;
this.transferred = 0;
}
public void write(byte[] b, int off, int len) throws IOException {
out.write(b, off, len);
this.transferred += len;
this.listener.transferred(this.transferred);
}
public void write(int b) throws IOException {
out.write(b);
this.transferred++;
this.listener.transferred(this.transferred);
}
}
}
这个类是对httpmime里的
MultipartEntity 类的复写
它提供了进度条的监听,如果需要此功能可以进行扩展。
同样如果不想导入httpmime源码,而是导入jar包的话,需要把这个类拿出来。作为自己的类进行扩展。
为了Android的开源精神,这份代码同样放到github上一份,欢迎fork和star。
library的下载地址:
github:基于HttpClientUtil的文件上传,提供进度条接口
csdn:基于HttpClient的文件上传,提供进度条接口