HttpClient MultipartEntityBuilder 上传文件
文章转载自:
http://blog.csdn.net/yan8024/article/details/46531901
http://www.51testing.com/html/56/n-3707756.html
https://blog.csdn.net/z69183787/article/details/78616463


在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;
- 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();
- }
- 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.完成项目代码:
- package 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());
- }
- }
- package 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());
- }
- }
- 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;
- }
- }
转载于: :http://blog.csdn.net/fengyuzhengfan/article/details/39941851
以下待研究:http://blog.csdn.net/zhouzme/article/details/18940279、htp://my.oschina.net/weichou/blog/352753
http://topmanopensource.iteye.com/blog/1605238(使用HttpurlConnection上传文件)
HttpClient MultipartEntityBuilder 上传文件的更多相关文章
- 使用HttpClient MultipartEntityBuilder 上传文件,并解决中文文件名乱码问题
遇到一种业务场景,前端上传的文件需要经过java服务转发至文件服务.期间遇到了原生HttpClient怎么使用的问题.怎么把MultipartFile怎么重新组装成Http请求发送出去的问题.文件中文 ...
- 转 Android网络编程之使用HttpClient批量上传文件 MultipartEntityBuilder
请尊重他人的劳动成果,转载请注明出处:Android网络编程之使用HttpClient批量上传文件 http://www.tuicool.com/articles/Y7reYb 我曾在<Andr ...
- Android 发送HTTP GET POST 请求以及通过 MultipartEntityBuilder 上传文件(二)
Android 发送HTTP GET POST 请求以及通过 MultipartEntityBuilder 上传文件第二版 上次粗略的写了相同功能的代码,这次整理修复了之前的一些BUG,结构也大量修改 ...
- C# 应用 - 使用 HttpClient 发起上传文件、下载文件请求
1. 示例代码 using System; using System.IO; using System.Net.Http; /// <summary> /// 下载文件 /// </ ...
- HttpClient中转上传文件
场景:客户端(浏览器)A---->选择文件上传---->服务器B---->中转文件---->服务器C---->返回结果---->服务器B---->客户端A 有 ...
- Android 发送HTTP GET POST 请求以及通过 MultipartEntityBuilder 上传文件
折腾了好几天的 HTTP 终于搞定了,经测试正常,不过是初步用例测试用的,因为后面还要修改先把当前版本保存在博客里吧. 其中POST因为涉及多段上传需要导入两个包文件,我用的是最新的 httpmine ...
- HttpClient 测试web API上传文件实例
1.使用HttpClient 测试上传文件并且设置header信息: using Lemon.Common; using Newtonsoft.Json; using System; using Sy ...
- java使用httpcomponents 上传文件
一.httpcomponents简介 httpcomponents 是apache下的用来负责创建和维护一个工具集的低水平Java组件集中在HTTP和相关协议的工程.我们可以用它在代码中直接发送htt ...
- Android利用网络编程HttpClient批量上传(一个)
请尊重他人的劳动成果.转载请注明出处:Android网络编程之使用HttpClient批量上传文件 我曾在<Android网络编程之使用HTTP訪问网络资源>一文中介绍过HttpCient ...
随机推荐
- JavaScript实现RSA加解密
在GitHub上找到jsencrypt.js对RSA加解密的工具文件,地址分别是:https://github.com/travist/jsencrypt和https://github.com/ope ...
- Mac截图操作,自定义快捷键
选择system preferences 下面能看到系统定义的快捷键,可以自己修改
- C#设计模式(13)——代理模式(Proxy Pattern)(转)
一.引言 在软件开发过程中,有些对象有时候会由于网络或其他的障碍,以至于不能够或者不能直接访问到这些对象,如果直接访问对象给系统带来不必要的复杂性,这时候可以在客户端和目标对象之间增加一层中间层,让代 ...
- Windows Java安装
jdk安装与配置jdk for windows1.下载官网地址:http://www.oracle.com/technetwork/java/javase/downloads/index.html2. ...
- 获取Type的三种方式
using System;using UnityEngine; public class Type_Test : MonoBehaviour{ private void Awake() { ...
- c# 中HttpClient访问Https网站
c# 中HttpClient访问Https网站,加入如下代码: handler = new HttpClientHandler() ;handler.AllowAutoRedirect = true; ...
- bochs模拟器创建映像文件 、写入文件并启动
安装 bochs,dd for windows,nasm,并将安装目录加入到环境变量中. 我用的bochs版本是2.6.8 1.用 bochs 中 bximage.exe 创建新的 img 文件 2. ...
- Kindle:自动追更之Calibre2脚本
#!/usr/bin/env python2 # vim:fileencoding=utf-8 from __future__ import unicode_literals, division, a ...
- echarts 图的点击事件(含:点击重复触发的问题及其解决方法)
今天用echarts的时候发现一个问题 鼠标指向不同地市触发一个事件展示该地区趋势图 但是但是后台中不管我第几次鼠标指向都会触发两次指向事件 现在贴出解决办法: 问题完美解决.但是为什么会调用两次, ...
- 原创《开源一个用 vue 写的树层级组件 vue-ztree》
最近由于后台管理项目的需要,页面需要制作一个无限树的需求,我第一感就想到了插件 ztree,不过我觉得它太大了,还是自己动手丰衣足食吧. ztree 的 demo 地址:http://www.tree ...