我曾在《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() |
主要方法说明:
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.完成项目代码:
- 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;
- }
- }
相关推荐
这个过程涉及多个技术层面,包括客户端的Android编程、网络通信以及服务器端的ASP.NET处理。本文将详细讲解如何实现这一功能。 一、Android端的实现 1. **创建文件选择器**: 首先,你需要一个文件选择器允许用户...
在Android应用开发中,网络通信是必不可少的一部分,它使得设备能够与远程服务器交换数据,实现各种功能,如获取用户信息、下载更新、上传图片等。本压缩包包含的"Android 网络通信的六种方式示例代码"将详细展示...
2. **HttpClient(已废弃)**:虽然在Android API 23及以上版本被标记为废弃,但HttpClient曾经是广泛使用的网络通信工具。它提供了丰富的功能,如Cookie管理、SSL支持等。了解这个库对于理解早期Android应用很有...
在Java编程中,上传和下载是常见的网络操作,特别是在开发Web应用、文件共享或云存储服务时。要实现带有进度条的功能,可以提供更好的用户体验,让用户了解文件传输的状态。以下是一些关键知识点: 1. **Java IO流*...
【标题】"S02.01-Exercise-Networking (1).zip" 提供的是一组关于网络编程的练习,可能包含代码、文档或示例,用于学习和理解如何在Android平台上进行网络操作。 【描述】虽然描述简单,但我们可以推测这可能是一个...
这个压缩包文件 "Android_Volley" 很可能包含了Volley框架的源代码,使得开发者可以深入理解其内部机制,优化自定义的网络请求。 Volley 的主要特性包括: 1. **缓存策略**:Volley 提供了内存和磁盘两级缓存,...
如果你是初学者,通过阅读这样的程序代码,可以学习到如何使用Java进行网络编程,如使用HttpURLConnection或Apache HttpClient库来发起HTTP请求,处理网络数据,以及如何设计和实现多线程下载策略等。 在学习过程中...
然而,对于理解网络请求处理的基本原理和异步编程模式,`android-async-http`仍然具有很高的学习价值。 总结,`android-async-http-master`作为一款成熟的Android异步HTTP库,它的设计思路和实现方式为开发者提供了...
虽然这里没有明确提到具体的Apache项目,但在安卓开发中,Apache HttpClient或者HttpURLConnection常用于网络通信,下载或上传视频文件;而Apache Commons IO库则提供了文件操作的便捷方法。 【资源达人分享计划】...
这需要了解相关协议,并使用如Apache HttpClient或OkHttp等库来实现网络连接。 9. **性能优化**:对于大文件或者大量文件的处理,性能优化是必不可少的,可能需要采用缓存策略、批量操作等方式来提升效率。 10. **...
在Java或Python等编程语言中,我们可以使用HttpURLConnection或HttpClient类来实现这一过程。 2. **网络请求库**:为了简化HTTP请求,开发者常使用第三方库,如Java的OkHttp、Android的Volley或Retrofit,或者...
本文主要介绍如何使用Java编程语言批量采集豌豆荚网站上的Android应用图标和包名。这对于Android主题开发者来说非常有用,因为替换第三方应用的图标需要知道应用的包名。下面我们将深入探讨实现这一功能的关键技术点...
通过深入理解Volley源代码,你可以学习到Android网络编程的最佳实践,包括异步处理、线程管理、缓存策略等。这对于开发高效、稳定的网络应用具有重要意义。同时,你还可以根据项目需求对Volley进行扩展或定制,比如...
Volley是Google推出的一款高效的Android网络通信框架,其设计目标是为了简化网络请求处理,并优化了内存使用和响应速度,尤其适合数据量较小、频繁交互的网络操作,如获取JSON数据或图片加载等。Volley的核心理念是...
在Xamarin开发中,异步加载和缓存图片是一项关键技术,它对于提高移动应用的性能和用户体验至关...通过使用异步编程、内存和磁盘缓存,配合生命周期管理和性能优化策略,开发者可以构建出高效、流畅的图片显示功能。
可以使用内置的网络库(如Android的HttpURLConnection)或第三方库(如OkHttp、Volley)。请求可能包含URL、HTTP方法(GET或POST)、请求头以及可能的请求体。 2. **多线程**:为了提高下载速度并避免阻塞用户界面...
下面将详细探讨可能导致这一现象的原因以及与之相关的Android开发、Java编程和Apache相关知识点。 首先,Android系统是基于Java语言构建的,因此应用的大部分代码都是用Java编写的。Java作为一种面向对象的语言,其...
例如,我们可以使用Java的HttpURLConnection或者HttpClient类来建立连接,发送请求,并接收服务器的响应。对于读取操作,我们可能需要发送一个GET请求,获取JSP文件的内容;对于写入操作,可能是POST或PUT请求,将...
另外,对于敏感操作(如批量发送、修改模板),建议使用沙箱环境测试,避免影响生产环境。 ### 6. 博客教程 如果你在使用过程中遇到问题,可以在博主的博客中搜索“腾讯云sms短信服务”相关的教程,获取更详细的...