Android利用网络编程HttpClient批量上传(一个)

Android利用网络编程HttpClient批量上传(一个)

大家好,又见面了,我是全栈君,今天给大家准备了Idea注册码。

请尊重他人的劳动成果。转载请注明出处: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类型。所以在server端我们能够通过request.getPart(“keyname”)方式获取相应key的数据。也能够通过request.getParts()方式获取client通过以上三种方法提交全部数据。

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端项目核心代码:

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;		

代码分析: 

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

     server端能够通过获取名为fileTypes的參数。然后将其拆分成字符数组,就可以得到要保存文件的类型。


server端项目核心代码:

server段主要用到Servlet3.0API,主要用到的方法有:

1.      request.getParameter(“”);//获取client通过addTextBody方法加入的String类型的数据。

2.      request.getPart(“”);//获取client通过addBinaryBodyaddPartaddTextBody方法加入的指定数据,返回Part类型的对象。

3.      request.getParts();//获取client通过addBinaryBodyaddPartaddTextBody方法加入的全部数据,返回Collection<Part>类型的对象。

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

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

String fileTypes=request.getParameter("fileTypes");//获取client上传的全部文件类型
String[]typeArray=fileTypes.substring(1).split("\\.");//将文件类型字符串拆分成String数组
try {
	Iterator<Part>iterator=request.getParts().iterator();
	int count=0;
	while (iterator.hasNext()) {//遍历client上传的全部文件				
		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();
}

代码分析: 

         server端是通过Servlet实现的,通过调用request.getParameter(“fileTypes”)方法来获取client上传的全部文件类型,然后将文件类型字符串拆分成String数组。通过request.getParts()方法取出client通过addBinaryBodyaddPartaddTextBody上传的全部数据,然后遍历数据集合就可以进行文件的保存。

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


程序执行效果图:


Android使用HttpClient上传数据

3.完毕项目代码:


MainActivity.java

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());
	}
}
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 {
						//将数据发送给server失败
					}
				} 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;		
	}
}

版权声明:本文博客原创文章。博客,未经同意,不得转载。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/117556.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • PHP UEditor富文本编辑器 显示 后端配置项没有正常加载,上传插件不能正常使用…

    PHP UEditor富文本编辑器 显示 后端配置项没有正常加载,上传插件不能正常使用…

    2021年10月11日
  • 链路层链路发现协议(LLDP)讲解「建议收藏」

    链路层链路发现协议(LLDP)讲解「建议收藏」一、LLDP协议概述 随着网络技术的发展,接入网络的设备的种类越来越多,配置越来越复杂,来自不同设备厂商的设备也往往会增加自己特有的功能,这就导致在一个网络中往往会有很多具有不同特性的、来自不同厂商的设备,为了方便对这样的网络进行管理,就需要使得不同厂商的设备能够在网络中相互发现并交互各自的系统及配置信息。 LLDP(LinkLayerDiscoveryProtocol,链路层发现协

  • 什么是授权码,它又是如何设置?

    什么是授权码,它又是如何设置?

  • java标识符是什么_Java 标识符「建议收藏」

    java标识符是什么_Java 标识符「建议收藏」什么是标识符标识符就是程序员在编写Java程序时,自定义的一些名字。例如第一个Java程序里关键字class后跟的HelloWorld,就是我们自定义的类名。类名就属于标识符的一种。标识符除了应用在类名上,还可以用在接口、变量、方法名、包名上。(要求同学们先记住,以后会详细见到这些)。标识符命名规则标识符由字母、下划线、美元符或数字组成标识符不能以数字开头,不能是关键字标识符严格区分大…

  • string转换为jsonarray_jsonobject转jsonarray

    string转换为jsonarray_jsonobject转jsonarray//创建JSONArray,把JSONObject放到JSONArrayJSONArrayja=newJSONArray();//获取JSONArrayJSONArrayitems=response.getJSONArray(“items”);if(!items.isEmpty()){//获取JSO…

  • hashmap线程不安全问题_为什么HashMap线程不安全

    hashmap线程不安全问题_为什么HashMap线程不安全HashMap的线程不安全主要体现在下面两个方面:1.在JDK1.7中,当并发执行扩容操作时会造成环形链和数据丢失的情况。2.在JDK1.8中,在并发执行put操作时会发生数据覆盖的情况。JDK1.7在JDK1.7中,扩容数据时要进行把原数据迁移到新的位置,使用的方法://数据迁移的方法,头插法添加元素voidtransfer(Entry[]newTable,booleanrehash){intnewCapacity=newTable.length;     

    2022年10月11日

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号