Android网络编程之使用HttpClient批量上传文件
2016-01-22 11:05
741 查看
转载:http://www.mamicode.com/info-detail-247544.html
转载:http://www.itnose.net/detail/6143194.html
感谢原作者的无私奉献。
主要方法说明:
addBinaryBody、addPart、addTextBody方法用于添加要上传的数据,从上面的表格中可以发现用于添加数据的方法,都是key-value类型。所以在服务器端我们可以通过request.getPart("keyname")方式获取对应key的数据。也可以通过request.getParts()方式获取客户端通过以上三种方法提交所有数据。
1.通过addBinaryBody方法直接可以添加File、InputStream、byte[]类型的数据。
2.通过addPart方法只能添加ContentBody类型的数据,在org.apache.http.entity.mime.content包中已经提供了String、File以及InputStream对应的ContentBody类型的子类,如FileBody、InputStreamBody、StringBody,通过这些类我们可以将String、File以及InputStream类型的数据转换成ContentBody类型的数据。
3.通过addTextBody方法我们可以很方便的添加文本数据。
在这里我用的是最新版的HttpCient,大家可以从http://hc.apache.org/downloads.cgi上下载所需要的jar包,如果上面的网站打不开,大家也不用担心,我已经将项目中所需要的jar包上传到CSDN上《httpcomponents-client-4.3.5-bin.zip》需要的朋友可以去下载。
代码分析:
上面代码主要实现了多文件上传,为了方便服务器端保存文件,上面代码设置了名称为fileTypes的参数,fileTypes是由上传的文件类型名拼接成的字符串,如”.jpg.png.docx“;
服务器端可以通过获取名为fileTypes的参数,然后将其拆分成字符数组,即可得到要保存文件的类型。
1. request.getParameter("");//获取客户端通过addTextBody方法添加的String类型的数据。
2. request.getPart("");//获取客户端通过addBinaryBody、addPart、addTextBody方法添加的指定数据,返回Part类型的对象。
3. request.getParts();//获取客户端通过addBinaryBody、addPart、addTextBody方法添加的所有数据,返回Collection<Part>类型的对象。
4. part.getName();//获取上传文件的名称即上传时指定的key。
5. part.getSize()//获取上传文件的大小单位为字节。
代码分析:
服务器端是通过Servlet实现的,通过调用request.getParameter("fileTypes")方法来获取客户端上传的所有文件类型,然后将文件类型字符串拆分成String数组。通过request.getParts()方法取出客户端通过addBinaryBody、addPart、addTextBody上传的所有数据,然后遍历数据集合即可进行文件的保存。
由于事先和客户端协定,添加上传文件的顺序在添加请求参数之前,所以可以根据拆分出的文件类型数组的长度判断出客户端上传文件的个数,因此当上面代码遍历超出了类型数组的长度时程序跳出循环,不再进行文件的保存,因为下面的Part都是些参数,而不是要保存的文件了。
UploadService.java
转载:http://www.itnose.net/detail/6143194.html
感谢原作者的无私奉献。
1.预备知识:
在HttpCient4.3之前上传文件主要使用MultipartEntity这个类,但现在这个类已经不在推荐使用了。随之替代它的类是MultipartEntityBuilder。下面让我们了解一下MultipartEntityBuilder类:
MultipartEntityBuilder这个类主要用于创建HttpEntity。它的主要方法有:修饰符和类型 | 方法和描述 |
MultipartEntityBuilder | addBinaryBody(String name, byte[] b) 将字节数组以二进制的形式添加数据。 |
MultipartEntityBuilder | addBinaryBody(String name, byte[] b, ContentType contentType, String filename) 将字节数组以二进制的形式添加数据。 |
MultipartEntityBuilder | addBinaryBody(String name, File file) 将文件以二进制的形式添加数据。 |
MultipartEntityBuilder | addBinaryBody(String name, File file, ContentType contentType, String filename) 将文件以二进制的形式添加数据。 |
MultipartEntityBuilder | addBinaryBody(String name, InputStream stream) |
MultipartEntityBuilder | addBinaryBody(String name, InputStream stream, ContentType contentType, String filename) 将输入流以二进制的形式添加数据。 |
MultipartEntityBuilder | addPart(String name, ContentBody contentBody) 添加ContentBody 类型的数据。 |
MultipartEntityBuilder | addTextBody(String name, String text) 添加文本数据。 |
MultipartEntityBuilder | addTextBody(String name, String text, ContentType contentType) 以指定的内容类型添加文本数据。 |
HttpEntity | build() 创建一个HttpEntity。 |
static MultipartEntityBuilder | create() 创建一个MultipartEntityBuilder对象。 |
MultipartEntityBuilder | setBoundary(String boundary) 设置边界。 |
MultipartEntityBuilder | setCharset(Charset charset) 设置请求的编码格式。 |
MultipartEntityBuilder | setLaxMode() |
MultipartEntityBuilder | setMode(HttpMultipartMode mode) 设置模式。 |
MultipartEntityBuilder | setStrictMode() |
addBinaryBody、addPart、addTextBody方法用于添加要上传的数据,从上面的表格中可以发现用于添加数据的方法,都是key-value类型。所以在服务器端我们可以通过request.getPart("keyname")方式获取对应key的数据。也可以通过request.getParts()方式获取客户端通过以上三种方法提交所有数据。
1.通过addBinaryBody方法直接可以添加File、InputStream、byte[]类型的数据。
2.通过addPart方法只能添加ContentBody类型的数据,在org.apache.http.entity.mime.content包中已经提供了String、File以及InputStream对应的ContentBody类型的子类,如FileBody、InputStreamBody、StringBody,通过这些类我们可以将String、File以及InputStream类型的数据转换成ContentBody类型的数据。
3.通过addTextBody方法我们可以很方便的添加文本数据。
2.通过HttpCient上传文件
Android端需要添加httpcore-4.3.2.jar、httpmime-4.3.5.jar两个包。两个包缺一不可。在这里我用的是最新版的HttpCient,大家可以从http://hc.apache.org/downloads.cgi上下载所需要的jar包,如果上面的网站打不开,大家也不用担心,我已经将项目中所需要的jar包上传到CSDN上《httpcomponents-client-4.3.5-bin.zip》需要的朋友可以去下载。
Android端项目核心代码:
HttpClient client=new DefaultHttpClient();// 开启一个客户端 HTTP 请求
HttpPost post = new HttpPost(url);//创建 HTTP POST 请求
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
// builder.setCharset(Charset.forName("uft-8"));//设置请求的编码格式
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);//设置浏览器兼容模式
int count=0;for (File file:files) {
// FileBody fileBody = new FileBody(file);//把文件转换成流对象FileBody// builder.addPart("file"+count, fileBody); builder.addBinaryBody("file"+count, file);
count++;
}
builder.addTextBody("method", params.get("method"));//设置请求参数
builder.addTextBody("fileTypes", params.get("fileTypes"));//设置请求参数
HttpEntity entity = builder.build();// 生成 HTTP POST 实体
post.setEntity(entity);//设置请求参数
HttpResponse response = client.execute(post);// 发起请求 并返回请求的响应
if (response.getStatusLine().getStatusCode()==200)
{ return true;}return false;
代码分析:
上面代码主要实现了多文件上传,为了方便服务器端保存文件,上面代码设置了名称为fileTypes的参数,fileTypes是由上传的文件类型名拼接成的字符串,如”.jpg.png.docx“;
服务器端可以通过获取名为fileTypes的参数,然后将其拆分成字符数组,即可得到要保存文件的类型。
服务器端项目核心代码:
服务器段主要用到Servlet3.0的API,主要用到的方法有:1. request.getParameter("");//获取客户端通过addTextBody方法添加的String类型的数据。
2. request.getPart("");//获取客户端通过addBinaryBody、addPart、addTextBody方法添加的指定数据,返回Part类型的对象。
3. request.getParts();//获取客户端通过addBinaryBody、addPart、addTextBody方法添加的所有数据,返回Collection<Part>类型的对象。
4. part.getName();//获取上传文件的名称即上传时指定的key。
5. part.getSize()//获取上传文件的大小单位为字节。
String fileTypes=request.getParameter("fileTypes");//获取客户端上传的所有文件类型
String[]typeArray=fileTypes.substring(1).split("\\.");//将文件类型字符串拆分成String数组
try { Iterator<Part>iterator=request.getParts().iterator(); int count=0; while (iterator.hasNext()) {//遍历客户端上传的所有文件 if (count>=typeArray.length)break;//如果超出文件类型数组的大小则跳出循环 Part part = (Part) iterator.next(); // System.out.println("part.getSize()"+part.getSize());//获取上传文件的大小// System.out.println("part.getName()"+part.getName());//获取上传文件的名及添加数据时的key名 File file=new File("E:\\upload\\"+count+"."+typeArray[count++]); InputStream inputStream=part.getInputStream(); FileOutputStream fos=new FileOutputStream(file); byte[]buffer=new byte[1024]; int len=0; while ((len=inputStream.read(buffer))!=-1) { fos.write(buffer,0, len); }inputStream.close(); fos.close(); }}catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace();}
代码分析:
服务器端是通过Servlet实现的,通过调用request.getParameter("fileTypes")方法来获取客户端上传的所有文件类型,然后将文件类型字符串拆分成String数组。通过request.getParts()方法取出客户端通过addBinaryBody、addPart、addTextBody上传的所有数据,然后遍历数据集合即可进行文件的保存。
由于事先和客户端协定,添加上传文件的顺序在添加请求参数之前,所以可以根据拆分出的文件类型数组的长度判断出客户端上传文件的个数,因此当上面代码遍历超出了类型数组的长度时程序跳出循环,不再进行文件的保存,因为下面的Part都是些参数,而不是要保存的文件了。
程序运行效果图:
3.完成项目代码:
MainActivity.javapackage com.jph.ufh.activity;import java.io.File;import java.util.ArrayList;import java.util.HashMap;import java.util.Map;import com.jph.ufh.R;import com.jph.ufh.service.UploadService;import android.app.Activity;import android.os.Bundle;import android.os.Environment;import android.os.Handler;import android.os.Message;import android.view.View;import android.widget.Toast;/** * 通过httpClient批量上传文件 * @author jph * Date:2014.10.09 */public class MainActivity extends Activity { private ArrayList<File>files; private Map<String, String>params; Handler mHandler=new Handler(){ @Override public void handleMessage(Message msg) { // TODO Auto-generated method stub switch (msg.what) { case UploadService.UPLOAD_SUCCESS: Toast.makeText(MainActivity.this, "上传成功", Toast.LENGTH_LONG).show(); break; } super.handleMessage(msg); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); files=new ArrayList<File>(); params=new HashMap<String, String>(); } public void upload(View v) { files.clear(); params.clear(); File file=new File(Environment.getExternalStorageDirectory(),"kaola.jpg"); File file2=new File(Environment.getExternalStorageDirectory(),"test.docx"); File file3=new File(Environment.getExternalStorageDirectory(),"test.jpg"); files.add(file); files.add(file2); files.add(file3); StringBuffer sbFileTypes=new StringBuffer(); for (File tempFile:files) { String fileName=tempFile.getName(); sbFileTypes.append(getFileType(fileName)); }params.put("fileTypes",sbFileTypes.toString()); params.put("method", "upload"); UploadService uploadService=new UploadService(mHandler); uploadService.uploadFileToServer(params, files); } /** * 获取文件的类型 * @param fileName :文件名 * @return 文件类型 */ private String getFileType(String fileName) { // TODO Auto-generated method stub return fileName.substring(fileName.lastIndexOf("."), fileName.length()); }}
UploadService.java
package com.jph.ufh.service;import java.io.File;import java.io.IOException;import java.util.ArrayList;import java.util.Map;import org.apache.http.HttpEntity;import org.apache.http.HttpResponse;import org.apache.http.client.ClientProtocolException;import org.apache.http.client.HttpClient;import org.apache.http.client.methods.HttpPost;import org.apache.http.entity.mime.HttpMultipartMode;import org.apache.http.entity.mime.MultipartEntityBuilder;import org.apache.http.impl.client.DefaultHttpClient;import android.os.Handler; /** * 采用HttpClient上传文件,支持多文件上传 * @author jph * Date:2014.10.09 */public class UploadService { private static String url="http://10.219.57.16:8080/ServerForUpload/ServletForUpload";// private static String url="http://10.110.6.58:8080/ServerForUpload/ServletForUpload"; public static final int UPLOAD_SUCCESS=0x123; public static final int UPLOAD_FAIL=0x124; private Handler handler; public UploadService(Handler handler) { // TODO Auto-generated constructor stub this.handler=handler; }/** * @param params 请求参数,包括请求的的方法参数method如:“upload”, * 请求上传的文件类型fileTypes如:“.jpg.png.docx” * @param files 要上传的文件集合 */ public void uploadFileToServer(final Map<String, String> params, final ArrayList<File>files) { // TODO Auto-generated method stub new Thread(new Runnable() { @Override public void run() { // TODO Auto-generated method stub try { if (uploadFiles(url,params,files)) { handler.sendEmptyMessage(UPLOAD_SUCCESS);//通知主线程数据发送成功 }else { //将数据发送给服务器失败 } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } }}).start(); } /** * @param url servlet的地址 * @param params 要传递的参数 * @param files 要上传的文件 * @return true if upload success else false * @throws ClientProtocolException * @throws IOException */ private boolean uploadFiles(String url,Map<String, String>params,ArrayList<File>files) throws ClientProtocolException, IOException { HttpClient client=new DefaultHttpClient();// 开启一个客户端 HTTP 请求 HttpPost post = new HttpPost(url);//创建 HTTP POST 请求 MultipartEntityBuilder builder = MultipartEntityBuilder.create();// builder.setCharset(Charset.forName("uft-8"));//设置请求的编码格式 builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);//设置浏览器兼容模式 int count=0; for (File file:files) {// FileBody fileBody = new FileBody(file);//把文件转换成流对象FileBody// builder.addPart("file"+count, fileBody); builder.addBinaryBody("file"+count, file); count++; } builder.addTextBody("method", params.get("method"));//设置请求参数 builder.addTextBody("fileTypes", params.get("fileTypes"));//设置请求参数 HttpEntity entity = builder.build();// 生成 HTTP POST 实体 post.setEntity(entity);//设置请求参数 HttpResponse response = client.execute(post);// 发起请求 并返回请求的响应 if (response.getStatusLine().getStatusCode()==200) { return true; }return false; }}
相关文章推荐
- 深度学习与计算机视觉系列(10)_细说卷积神经网络
- POJ 3436 ACM Computer Factory(拆点+前向星dinic)||(拆点+邻接矩阵dinic)||(不拆点+dinic))
- 网络编程(自定义图形界面浏览器-Tomcat服务端). 模拟IE 的请求
- TCP/IP协议 三次握手与四次挥手
- unix网络编程I卷之关于wait在不同系统中的表现扩展出来的问题
- iOS开发工具——网络封包分析工具Charles
- Linux曲径通幽:常用命令(网络通信命令)
- android 判断网络状态 (无网络 wifi 数据流量)
- curl --connect-timeout 判断国内外网络windows 批处理
- ngcordova 监控网络制式改变
- HTTP protocal
- ios 开发网络篇 - 数据缓存
- HTTP对外接口,如何增加签名机制
- 九大全球网络攻击实时追踪系统盘点
- 《HTTP权威指南》-第7章 缓存
- 《HTTP权威指南》-第6章 代理
- 《HTTP权威指南》-第5章 Web服务器
- HTTP 错误 404.17 - Not Found 请求的内容似乎是脚本,因而将无法由静态文件处理程序来处理。
- 提示网络状态并打开网络设置页面
- 金蝶盘点机条码数据採集器PDA,WIFI已经连接,可是PDA应用程序还是网络初始化不成功?