`

Android网络编程之使用HttpClient批量上传文件

阅读更多

我曾在《Android网络编程之使用HTTP访问网络资源》一文中介绍过HttpCient的使用,这里就不在累述了,感兴趣的朋友可以去看一下。在这里主要介绍如何通过HttpClient实现文件上传。

 

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() 

         

主要方法说明:

addBinaryBodyaddPartaddTextBody方法用于添加要上传的数据,从上面的表格中可以发现用于添加数据的方法,都是key-value类型。所以在服务器端我们可以通过request.getPart("keyname")方式获取对应key的数据。也可以通过request.getParts()方式获取客户端通过以上三种方法提交所有数据。

1.通过addBinaryBody方法直接可以添加FileInputStreambyte[]类型的数据。

2.通过addPart方法只能添加ContentBody类型的数据,在org.apache.http.entity.mime.content包中已经提供了StringFile以及InputStream对应的ContentBody类型的子类,如FileBodyInputStreamBodyStringBody通过这些类我们可以将StringFile以及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 plaincopy在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;         

代码分析: 

 

     上面代码主要实现了多文件上传,为了方便服务器端保存文件,上面代码设置了名称为fileTypes的参数,fileTypes是由上传的文件类型名拼接成的字符串,如”.jpg.png.docx“

     服务器端可以通过获取名为fileTypes的参数,然后将其拆分成字符数组,即可得到要保存文件的类型。

 

服务器端项目核心代码:

服务器段主要用到Servlet3.0API,主要用到的方法有:

1.      request.getParameter("");//获取客户端通过addTextBody方法添加的String类型的数据。

2.      request.getPart("");//获取客户端通过addBinaryBodyaddPartaddTextBody方法添加的指定数据,返回Part类型的对象。

3.      request.getParts();//获取客户端通过addBinaryBodyaddPartaddTextBody方法添加的所有数据,返回Collection<Part>类型的对象。

4.      part.getName();//获取上传文件的名称即上传时指定的key

5.      part.getSize()//获取上传文件的大小单位为字节。

 

[java] view plaincopy在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. }  

 

 

代码分析: 

 

         服务器端是通过Servlet实现的,通过调用request.getParameter("fileTypes")方法来获取客户端上传的所有文件类型,然后将文件类型字符串拆分成String数组。通过request.getParts()方法取出客户端通过addBinaryBodyaddPartaddTextBody上传的所有数据,然后遍历数据集合即可进行文件的保存。

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

 

程序运行效果图:


Android使用HttpClient上传数据
 

 

3.完成项目代码:


MainActivity.java
[java] view plaincopy在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. }  
UploadService.java
[java] view plaincopy在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. }  
分享到:
评论

相关推荐

    Android端将小文件上传到asp.net服务器

    这个过程涉及多个技术层面,包括客户端的Android编程、网络通信以及服务器端的ASP.NET处理。本文将详细讲解如何实现这一功能。 一、Android端的实现 1. **创建文件选择器**: 首先,你需要一个文件选择器允许用户...

    Android网络通信的六种方式示例代码.zip

    在Android应用开发中,网络通信是必不可少的一部分,它使得设备能够与远程服务器交换数据,实现各种功能,如获取用户信息、下载更新、上传图片等。本压缩包包含的"Android 网络通信的六种方式示例代码"将详细展示...

    Android应用源码之网络通信的六种方式示例代码.zip

    2. **HttpClient(已废弃)**:虽然在Android API 23及以上版本被标记为废弃,但HttpClient曾经是广泛使用的网络通信工具。它提供了丰富的功能,如Cookie管理、SSL支持等。了解这个库对于理解早期Android应用很有...

    java上传和下载

    在Java编程中,上传和下载是常见的网络操作,特别是在开发Web应用、文件共享或云存储服务时。要实现带有进度条的功能,可以提供更好的用户体验,让用户了解文件传输的状态。以下是一些关键知识点: 1. **Java IO流*...

    S02.01-Exercise-Networking (1).zip

    【标题】"S02.01-Exercise-Networking (1).zip" 提供的是一组关于网络编程的练习,可能包含代码、文档或示例,用于学习和理解如何在Android平台上进行网络操作。 【描述】虽然描述简单,但我们可以推测这可能是一个...

    AndroidVolley框架使用源代码

    这个压缩包文件 "Android_Volley" 很可能包含了Volley框架的源代码,使得开发者可以深入理解其内部机制,优化自定义的网络请求。 Volley 的主要特性包括: 1. **缓存策略**:Volley 提供了内存和磁盘两级缓存,...

    一个java编写的程序

    如果你是初学者,通过阅读这样的程序代码,可以学习到如何使用Java进行网络编程,如使用HttpURLConnection或Apache HttpClient库来发起HTTP请求,处理网络数据,以及如何设计和实现多线程下载策略等。 在学习过程中...

    android-async-http-master

    然而,对于理解网络请求处理的基本原理和异步编程模式,`android-async-http`仍然具有很高的学习价值。 总结,`android-async-http-master`作为一款成熟的Android异步HTTP库,它的设计思路和实现方式为开发者提供了...

    安卓格式工厂v1.8.6高级版 手机端视频转换器.txt打包整理.zip

    虽然这里没有明确提到具体的Apache项目,但在安卓开发中,Apache HttpClient或者HttpURLConnection常用于网络通信,下载或上传视频文件;而Apache Commons IO库则提供了文件操作的便捷方法。 【资源达人分享计划】...

    SDResourceManager

    这需要了解相关协议,并使用如Apache HttpClient或OkHttp等库来实现网络连接。 9. **性能优化**:对于大文件或者大量文件的处理,性能优化是必不可少的,可能需要采用缓存策略、批量操作等方式来提升效率。 10. **...

    下载图片的demo

    在Java或Python等编程语言中,我们可以使用HttpURLConnection或HttpClient类来实现这一过程。 2. **网络请求库**:为了简化HTTP请求,开发者常使用第三方库,如Java的OkHttp、Android的Volley或Retrofit,或者...

    java批量采集豌豆荚网站Android应用图标和包名

    本文主要介绍如何使用Java编程语言批量采集豌豆荚网站上的Android应用图标和包名。这对于Android主题开发者来说非常有用,因为替换第三方应用的图标需要知道应用的包名。下面我们将深入探讨实现这一功能的关键技术点...

    Volley源代码

    通过深入理解Volley源代码,你可以学习到Android网络编程的最佳实践,包括异步处理、线程管理、缓存策略等。这对于开发高效、稳定的网络应用具有重要意义。同时,你还可以根据项目需求对Volley进行扩展或定制,比如...

    volley.jar

    Volley是Google推出的一款高效的Android网络通信框架,其设计目标是为了简化网络请求处理,并优化了内存使用和响应速度,尤其适合数据量较小、频繁交互的网络操作,如获取JSON数据或图片加载等。Volley的核心理念是...

    xamarin异步加载并缓存图片库

    在Xamarin开发中,异步加载和缓存图片是一项关键技术,它对于提高移动应用的性能和用户体验至关...通过使用异步编程、内存和磁盘缓存,配合生命周期管理和性能优化策略,开发者可以构建出高效、流畅的图片显示功能。

    多图片下载

    可以使用内置的网络库(如Android的HttpURLConnection)或第三方库(如OkHttp、Volley)。请求可能包含URL、HTTP方法(GET或POST)、请求头以及可能的请求体。 2. **多线程**:为了提高下载速度并避免阻塞用户界面...

    安卓手机暖手宝v1.2 发热增大的软件.txt打包整理.zip

    下面将详细探讨可能导致这一现象的原因以及与之相关的Android开发、Java编程和Apache相关知识点。 首先,Android系统是基于Java语言构建的,因此应用的大部分代码都是用Java编写的。Java作为一种面向对象的语言,其...

    实例:往服务器中读写数据

    例如,我们可以使用Java的HttpURLConnection或者HttpClient类来建立连接,发送请求,并接收服务器的响应。对于读取操作,我们可能需要发送一个GET请求,获取JSP文件的内容;对于写入操作,可能是POST或PUT请求,将...

    腾讯云sms短信服务sdk含核心jar包:qcloudsms-1.0.5.jar

    另外,对于敏感操作(如批量发送、修改模板),建议使用沙箱环境测试,避免影响生产环境。 ### 6. 博客教程 如果你在使用过程中遇到问题,可以在博主的博客中搜索“腾讯云sms短信服务”相关的教程,获取更详细的...

Global site tag (gtag.js) - Google Analytics