HttpClient MultipartEntityBuilder 上传文件

 在HttpCient4.3以后上传文件主要使用的类是位于org.apache.http.entity.mime下的MultipartEntityBuilder(原先的MultipartEntity已经基本弃用了)。
  1.首先是设置上传的模式;
  setMode(HttpMultipartMode mode),其中mode主要有BROWSER_COMPATIBLE,RFC6532,STRICT三种,默认值是STRICT。
  2.其次是建立MultipartEntityBuilder对象,并添加须要上传的数据;
  a.利用MultipartEntityBuilder.create()来建立对象;
  b.addBinaryBody:以二进制的形式添加数据,能够添加File、InputStream、byte[]类型的数据。
  addBinaryBody(String name, File file, ContentType contentType, String filename)
  addBinaryBody(String name, InputStream stream, ContentType contentType, String filename)
  addBinaryBody(String name, byte[] b, ContentType contentType, String filename)
  c.addTextBody:添加文本数据
  addTextBody(String name, String text, ContentType contentType)
  d.addPart:以Key/Value的形式添加ContentBody类型的数据
  addPart(String name, ContentBody contentBody)
  更多函数能够参考:https://hc.apache.org/httpcomponents-client-ga/httpmime/apidocs/org/apache/http/entity/mime/MultipartEntityBuilder.html。在GACHA API中,主要是上传图片,因此在 测试中选用了addBinaryBody。其中,第一个参数name的值,是服务器已经定义好的,服务器会根据这个字段来读取咱们上传的文件流,不匹配则会报错。关于contentType,能够参考:http://tool.oschina.net/commons,不一样文件扩展名所对应的类型。而file/stream和fileName,就是咱们所要上传文件的信息。当用 浏览器的开发者工具查看API请求时,咱们会看到这些/参数基本位于API请求中的 Request Payload字段。
  3.而后是利用build()方法建立一个HttpEntity对象;
  4.最后将HttpEntity对象添加到指定的URL上,采用HttpPost的setEntity的方法;
  5.最后的最后,就是调用HttpClient对象发送请求,并获取服务器的响应
 

 

 在HttpCient4.3以前上传文件主要使用MultipartEntity这个类,但如今这个类已经不在推荐使用了。随之替代它的类是MultipartEntityBuilder。php

 

下面让咱们了解一下MultipartEntityBuilder类:

         MultipartEntityBuilder这个类主要用于建立HttpEntity。它的主要方法有:html

修饰符和类型java

方法和描述android

MultipartEntityBuilderapache

addBinaryBody(String name, byte[] b) api

将字节数组以二进制的形式添加数据。数组

MultipartEntityBuilder浏览器

addBinaryBody(String name, byte[] b, ContentType contentType, String filename) 服务器

将字节数组以二进制的形式添加数据。app

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.jarhttpmime-4.3.5.jar两个包。两个包缺一不可。

在这里我用的是最新版的HttpCient,你们能够从http://hc.apache.org/downloads.cgi上下载所须要的jar包,若是上面的网站打不开,你们也不用担忧,我已经将项目中所须要的jar包上传到CSDN上《httpcomponents-client-4.3.5-bin.zip》须要的朋友能够去下载。

      Android端项目核心代码:

[java]  view plain copy 在CODE上查看代码片 派生到个人代码片
  1. HttpClient client=new DefaultHttpClient();// 开启一个客户端 HTTP 请求   
  2. HttpPost post = new HttpPost(url);//建立 HTTP POST 请求    
  3. MultipartEntityBuilder builder = MultipartEntityBuilder.create();  
  4. //      builder.setCharset(Charset.forName("uft-8"));//设置请求的编码格式  
  5. builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);//设置浏览器兼容模式  
  6. int count=0;  
  7. for (File file:files) {  
  8. //          FileBody fileBody = new FileBody(file);//把文件转换成流对象FileBody  
  9. //          builder.addPart("file"+count, fileBody);  
  10.     builder.addBinaryBody("file"+count, file);  
  11.     count++;  
  12. }         
  13. builder.addTextBody("method", params.get("method"));//设置请求参数  
  14. builder.addTextBody("fileTypes", params.get("fileTypes"));//设置请求参数  
  15. HttpEntity entity = builder.build();// 生成 HTTP POST 实体        
  16. post.setEntity(entity);//设置请求参数  
  17. HttpResponse response = client.execute(post);// 发起请求 并返回请求的响应  
  18. if (response.getStatusLine().getStatusCode()==200) {  
  19.     return true;  
  20. }  
  21. return false;         
[java]  view plain  copy
  1. HttpClient client=new DefaultHttpClient();// 开启一个客户端 HTTP 请求   
  2. HttpPost post = new HttpPost(url);//建立 HTTP POST 请求    
  3. MultipartEntityBuilder builder = MultipartEntityBuilder.create();  
  4. //      builder.setCharset(Charset.forName("uft-8"));//设置请求的编码格式  
  5. builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);//设置浏览器兼容模式  
  6. int count=0;  
  7. for (File file:files) {  
  8. //          FileBody fileBody = new FileBody(file);//把文件转换成流对象FileBody  
  9. //          builder.addPart("file"+count, fileBody);  
  10.     builder.addBinaryBody("file"+count, file);  
  11.     count++;  
  12. }         
  13. builder.addTextBody("method", params.get("method"));//设置请求参数  
  14. builder.addTextBody("fileTypes", params.get("fileTypes"));//设置请求参数  
  15. HttpEntity entity = builder.build();// 生成 HTTP POST 实体        
  16. post.setEntity(entity);//设置请求参数  
  17. HttpResponse response = client.execute(post);// 发起请求 并返回请求的响应  
  18. if (response.getStatusLine().getStatusCode()==200) {  
  19.     return true;  
  20. }  
  21. 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()//获取上传文件的大小单位为字节。

 

[java]  view plain copy 在CODE上查看代码片 派生到个人代码片
  1. String fileTypes=request.getParameter("fileTypes");//获取客户端上传的全部文件类型  
  2. String[]typeArray=fileTypes.substring(1).split("\\.");//将文件类型字符串拆分红String数组  
  3. try {  
  4.     Iterator<Part>iterator=request.getParts().iterator();  
  5.     int count=0;  
  6.     while (iterator.hasNext()) {//遍历客户端上传的全部文件                
  7.         if (count>=typeArray.length)break;//若是超出文件类型数组的大小则跳出循环         
  8.         Part part = (Part) iterator.next();               
  9. //              System.out.println("part.getSize()"+part.getSize());//获取上传文件的大小  
  10. //              System.out.println("part.getName()"+part.getName());//获取上传文件的名及添加数据时的key名  
  11.         File file=new File("E:\\upload\\"+count+"."+typeArray[count++]);  
  12.         InputStream inputStream=part.getInputStream();  
  13.         FileOutputStream fos=new FileOutputStream(file);  
  14.         byte[]buffer=new byte[1024];  
  15.         int len=0;  
  16.         while ((len=inputStream.read(buffer))!=-1) {  
  17.             fos.write(buffer,0, len);  
  18.         }  
  19.         inputStream.close();  
  20.         fos.close();                      
  21.     }  
  22. }catch (Exception e) {  
  23.     // TODO Auto-generated catch block  
  24.     e.printStackTrace();  
  25. }  
[java]  view plain  copy
  1. String fileTypes=request.getParameter("fileTypes");//获取客户端上传的全部文件类型  
  2. String[]typeArray=fileTypes.substring(1).split("\\.");//将文件类型字符串拆分红String数组  
  3. try {  
  4.     Iterator<Part>iterator=request.getParts().iterator();  
  5.     int count=0;  
  6.     while (iterator.hasNext()) {//遍历客户端上传的全部文件                
  7.         if (count>=typeArray.length)break;//若是超出文件类型数组的大小则跳出循环         
  8.         Part part = (Part) iterator.next();               
  9. //              System.out.println("part.getSize()"+part.getSize());//获取上传文件的大小  
  10. //              System.out.println("part.getName()"+part.getName());//获取上传文件的名及添加数据时的key名  
  11.         File file=new File("E:\\upload\\"+count+"."+typeArray[count++]);  
  12.         InputStream inputStream=part.getInputStream();  
  13.         FileOutputStream fos=new FileOutputStream(file);  
  14.         byte[]buffer=new byte[1024];  
  15.         int len=0;  
  16.         while ((len=inputStream.read(buffer))!=-1) {  
  17.             fos.write(buffer,0, len);  
  18.         }  
  19.         inputStream.close();  
  20.         fos.close();                      
  21.     }  
  22. }catch (Exception e) {  
  23.     // TODO Auto-generated catch block  
  24.     e.printStackTrace();  
  25. }  

 

代码分析: 

         服务器端是经过Servlet实现的,经过调用request.getParameter("fileTypes")方法来获取客户端上传的全部文件类型,而后将文件类型字符串拆分红String数组。经过request.getParts()方法取出客户端经过addBinaryBody、addPart、addTextBody上传的全部数据,而后遍历数据集合便可进行文件的保存。

因为事先和客户端协定,添加上传文件的顺序在添加请求参数以前,因此能够根据拆分出的文件类型数组的长度判断出客户端上传文件的个数,所以当上面代码遍历超出了类型数组的长度时程序跳出循环,再也不进行文件的保存,由于下面的Part都是些参数,而不是要保存的文件了。

 

程序运行效果图:


Android使用HttpClient上传数据
 

 

3.完成项目代码:


MainActivity.java
[java]  view plain copy 在CODE上查看代码片 派生到个人代码片
  1. package com.jph.ufh.activity;  
  2.   
  3. import java.io.File;  
  4. import java.util.ArrayList;  
  5. import java.util.HashMap;  
  6. import java.util.Map;  
  7. import com.jph.ufh.R;  
  8. import com.jph.ufh.service.UploadService;  
  9. import android.app.Activity;  
  10. import android.os.Bundle;  
  11. import android.os.Environment;  
  12. import android.os.Handler;  
  13. import android.os.Message;  
  14. import android.view.View;  
  15. import android.widget.Toast;  
  16.   
  17. /** 
  18.  * 经过httpClient批量上传文件 
  19.  * @author jph 
  20.  * Date:2014.10.09   
  21.  */  
  22. public class MainActivity extends Activity {  
  23.     private ArrayList<File>files;  
  24.     private Map<String, String>params;  
  25.     Handler mHandler=new Handler(){  
  26.         @Override  
  27.         public void handleMessage(Message msg) {  
  28.             // TODO Auto-generated method stub  
  29.             switch (msg.what) {  
  30.             case UploadService.UPLOAD_SUCCESS:  
  31.                 Toast.makeText(MainActivity.this, "上传成功", Toast.LENGTH_LONG).show();  
  32.                 break;            
  33.             }  
  34.             super.handleMessage(msg);  
  35.         }         
  36.     };  
  37.     @Override  
  38.     protected void onCreate(Bundle savedInstanceState) {  
  39.         super.onCreate(savedInstanceState);  
  40.         setContentView(R.layout.activity_main);       
  41.         files=new ArrayList<File>();  
  42.         params=new HashMap<String, String>();  
  43.           
  44.     }  
  45.     public void upload(View v) {  
  46.         files.clear();  
  47.         params.clear();  
  48.         File file=new File(Environment.getExternalStorageDirectory(),"kaola.jpg");  
  49.         File file2=new File(Environment.getExternalStorageDirectory(),"test.docx");  
  50.         File file3=new File(Environment.getExternalStorageDirectory(),"test.jpg");  
  51.         files.add(file);  
  52.         files.add(file2);  
  53.         files.add(file3);  
  54.         StringBuffer sbFileTypes=new StringBuffer();  
  55.         for (File tempFile:files) {  
  56.             String fileName=tempFile.getName();  
  57.             sbFileTypes.append(getFileType(fileName));            
  58.         }  
  59.         params.put("fileTypes",sbFileTypes.toString());  
  60.         params.put("method", "upload");  
  61.         UploadService uploadService=new UploadService(mHandler);  
  62.         uploadService.uploadFileToServer(params, files);  
  63.     }  
  64.     /** 
  65.      * 获取文件的类型 
  66.      * @param fileName :文件名 
  67.      * @return 文件类型 
  68.      */  
  69.     private String getFileType(String fileName) {  
  70.         // TODO Auto-generated method stub  
  71.         return fileName.substring(fileName.lastIndexOf("."), fileName.length());  
  72.     }  
  73. }  
[java]  view plain  copy
  1. package com.jph.ufh.activity;  
  2.   
  3. import java.io.File;  
  4. import java.util.ArrayList;  
  5. import java.util.HashMap;  
  6. import java.util.Map;  
  7. import com.jph.ufh.R;  
  8. import com.jph.ufh.service.UploadService;  
  9. import android.app.Activity;  
  10. import android.os.Bundle;  
  11. import android.os.Environment;  
  12. import android.os.Handler;  
  13. import android.os.Message;  
  14. import android.view.View;  
  15. import android.widget.Toast;  
  16.   
  17. /** 
  18.  * 经过httpClient批量上传文件 
  19.  * @author jph 
  20.  * Date:2014.10.09   
  21.  */  
  22. public class MainActivity extends Activity {  
  23.     private ArrayList<File>files;  
  24.     private Map<String, String>params;  
  25.     Handler mHandler=new Handler(){  
  26.         @Override  
  27.         public void handleMessage(Message msg) {  
  28.             // TODO Auto-generated method stub  
  29.             switch (msg.what) {  
  30.             case UploadService.UPLOAD_SUCCESS:  
  31.                 Toast.makeText(MainActivity.this, "上传成功", Toast.LENGTH_LONG).show();  
  32.                 break;            
  33.             }  
  34.             super.handleMessage(msg);  
  35.         }         
  36.     };  
  37.     @Override  
  38.     protected void onCreate(Bundle savedInstanceState) {  
  39.         super.onCreate(savedInstanceState);  
  40.         setContentView(R.layout.activity_main);       
  41.         files=new ArrayList<File>();  
  42.         params=new HashMap<String, String>();  
  43.           
  44.     }  
  45.     public void upload(View v) {  
  46.         files.clear();  
  47.         params.clear();  
  48.         File file=new File(Environment.getExternalStorageDirectory(),"kaola.jpg");  
  49.         File file2=new File(Environment.getExternalStorageDirectory(),"test.docx");  
  50.         File file3=new File(Environment.getExternalStorageDirectory(),"test.jpg");  
  51.         files.add(file);  
  52.         files.add(file2);  
  53.         files.add(file3);  
  54.         StringBuffer sbFileTypes=new StringBuffer();  
  55.         for (File tempFile:files) {  
  56.             String fileName=tempFile.getName();  
  57.             sbFileTypes.append(getFileType(fileName));            
  58.         }  
  59.         params.put("fileTypes",sbFileTypes.toString());  
  60.         params.put("method", "upload");  
  61.         UploadService uploadService=new UploadService(mHandler);  
  62.         uploadService.uploadFileToServer(params, files);  
  63.     }  
  64.     /** 
  65.      * 获取文件的类型 
  66.      * @param fileName :文件名 
  67.      * @return 文件类型 
  68.      */  
  69.     private String getFileType(String fileName) {  
  70.         // TODO Auto-generated method stub  
  71.         return fileName.substring(fileName.lastIndexOf("."), fileName.length());  
  72.     }  
  73. }  
UploadService.java
[java]  view plain copy print ? 在CODE上查看代码片 派生到个人代码片
  1. package com.jph.ufh.service;  
  2.   
  3. import java.io.File;  
  4. import java.io.IOException;  
  5. import java.util.ArrayList;  
  6. import java.util.Map;  
  7. import org.apache.http.HttpEntity;  
  8. import org.apache.http.HttpResponse;  
  9. import org.apache.http.client.ClientProtocolException;  
  10. import org.apache.http.client.HttpClient;  
  11. import org.apache.http.client.methods.HttpPost;  
  12. import org.apache.http.entity.mime.HttpMultipartMode;  
  13. import org.apache.http.entity.mime.MultipartEntityBuilder;  
  14. import org.apache.http.impl.client.DefaultHttpClient;  
  15.   
  16. import android.os.Handler;  
  17.    
  18. /** 
  19.  * 采用HttpClient上传文件,支持多文件上传 
  20.  * @author jph 
  21.  * Date:2014.10.09 
  22.  */  
  23. public class UploadService {  
  24.     private static String url="http://10.219.57.16:8080/ServerForUpload/ServletForUpload";  
  25. //  private static String url="http://10.110.6.58:8080/ServerForUpload/ServletForUpload";  
  26.     public static final int UPLOAD_SUCCESS=0x123;  
  27.     public static final int UPLOAD_FAIL=0x124;  
  28.     private Handler handler;  
  29.     public UploadService(Handler handler) {  
  30.         // TODO Auto-generated constructor stub  
  31.         this.handler=handler;  
  32.     }     
  33.     /** 
  34.      * @param params 请求参数,包括请求的的方法参数method如:“upload”, 
  35.      * 请求上传的文件类型fileTypes如:“.jpg.png.docx” 
  36.      * @param files 要上传的文件集合 
  37.      */  
  38.     public void uploadFileToServer(final Map<String, String> params, final ArrayList<File>files) {  
  39.         // TODO Auto-generated method stub    
  40.         new Thread(new Runnable() {           
  41.             @Override  
  42.             public void run() {  
  43.                 // TODO Auto-generated method stub  
  44.                 try {  
  45.                      if (uploadFiles(url,params,files)) {  
  46.                         handler.sendEmptyMessage(UPLOAD_SUCCESS);//通知主线程数据发送成功  
  47.                     }else {  
  48.                         //将数据发送给服务器失败  
  49.                     }  
  50.                 } catch (Exception e) {  
  51.                     // TODO Auto-generated catch block  
  52.                     e.printStackTrace();  
  53.                 }                 
  54.             }  
  55.         }).start();  
  56.     }  
  57.     /** 
  58.      * @param url servlet的地址 
  59.      * @param params 要传递的参数 
  60.      * @param files 要上传的文件 
  61.      * @return true if upload success else false 
  62.      * @throws ClientProtocolException 
  63.      * @throws IOException 
  64.      */  
  65.     private boolean uploadFiles(String url,Map<String, String>params,ArrayList<File>files) throws ClientProtocolException, IOException {  
  66.         HttpClient client=new DefaultHttpClient();// 开启一个客户端 HTTP 请求   
  67.         HttpPost post = new HttpPost(url);//建立 HTTP POST 请求    
  68.         MultipartEntityBuilder builder = MultipartEntityBuilder.create();  
  69. //      builder.setCharset(Charset.forName("uft-8"));//设置请求的编码格式  
  70.         builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);//设置浏览器兼容模式  
  71.         int count=0;  
  72.         for (File file:files) {  
  73. //          FileBody fileBody = new FileBody(file);//把文件转换成流对象FileBody  
  74. //          builder.addPart("file"+count, fileBody);  
  75.             builder.addBinaryBody("file"+count, file);  
  76.             count++;  
  77.         }         
  78.         builder.addTextBody("method", params.get("method"));//设置请求参数  
  79.         builder.addTextBody("fileTypes", params.get("fileTypes"));//设置请求参数  
  80.         HttpEntity entity = builder.build();// 生成 HTTP POST 实体        
  81.         post.setEntity(entity);//设置请求参数  
  82.         HttpResponse response = client.execute(post);// 发起请求 并返回请求的响应  
  83.         if (response.getStatusLine().getStatusCode()==200) {  
  84.             return true;  
  85.         }  
  86.         return false;         
  87.     }  
  88. }  

转载于: :http://blog.csdn.net/fengyuzhengfan/article/details/39941851

 

如下待研究:http://blog.csdn.net/zhouzme/article/details/18940279htp://my.oschina.net/weichou/blog/352753

        

        http://topmanopensource.iteye.com/blog/1605238(使用HttpurlConnection上传文件)

相关文章
相关标签/搜索