ANDROID批量文件上传(附Demo文件)
2015-08-04 16:18
591 查看
前言
此篇主要介绍android的批量文件上传(从相册选择图片并上传)。客户端采用HttpClient和Http协议共2种上传方式。
服务端采用Spring MVC接收批量文件上传。
ANDROID客户端
1、HttpClient方式上传
准备文件
httpmime-4.1.1.jar (源码里面libs文件夹下)代码中需要使用到此jar文件中的MultipartEntity类。这是Apache的一个jar包,不是android自带的。
代码
//网络请求需要开启新的线程,不能在主线程中操作 Runnable multiThread = new Runnable() { @Override public void run() { try { multiUploadFile1(); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public void multiUploadFile1 () throws UnsupportedEncodingException { //HttpClient对象 HttpClient httpClient = new DefaultHttpClient(); //采用POST的请求方式 //这是上传服务地址http://10.0.2.2:8080/WebAppProject/main.do?method=upload2 HttpPost httpPost = new HttpPost("http://10.0.2.2:8080/WebAppProject/main.do?method=upload2"); //MultipartEntity对象,需要httpmime-4.1.1.jar文件。 MultipartEntity multipartEntity = new MultipartEntity(); //StringBody对象,参数 StringBody param = new StringBody("参数内容"); multipartEntity.addPart("param1",param); //filesPath为List<String>对象,里面存放的是需要上传的文件的地址 for (String path:filesPath) { //FileBody对象,需要上传的文件 ContentBody file = new FileBody( new File(path)); multipartEntity.addPart("file",file); } //将MultipartEntity对象赋值给HttpPost httpPost.setEntity(multipartEntity); HttpResponse response = null; try { //执行请求,并返回结果HttpResponse response = httpClient.execute(httpPost); } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } //上传成功后返回 if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { System.out.println("-->success"); } else { System.out.println("-->failure"); } } };
运行很简单:
new Thread(multiThread).start();
2、HTTP协议上传
此种方式在网上也很多,下面的HTTP协议部分的代码是从网上Copy的。public static String post(String path, Map<String, String> params, FormFile[] files,Handler handler) throws Exception{ try { final String BOUNDARY = "---------------------------7da2137580612"; //数据分隔线 final String endline = "--" + BOUNDARY + "--\r\n";//数据结束标志 int fileDataLength = 0; //文件长度 for(FormFile uploadFile : files){//得到文件类型数据的总长度 StringBuilder fileExplain = new StringBuilder(); fileExplain.append("--"); fileExplain.append(BOUNDARY); fileExplain.append("\r\n"); fileExplain.append("Content-Disposition: form-data;name=\""+ uploadFile.getParameterName()+"\";filename=\""+ uploadFile.getFilname() + "\"\r\n"); fileExplain.append("Content-Type: "+ uploadFile.getContentType()+"\r\n\r\n"); fileExplain.append("\r\n"); fileDataLength += fileExplain.length(); if(uploadFile.getInStream()!=null){ if (uploadFile.getFile() != null) { fileDataLength += uploadFile.getFile().length(); } else { fileDataLength += uploadFile.getFileSize(); } }else{ fileDataLength += uploadFile.getData().length; } } StringBuilder textEntity = new StringBuilder(); for (Map.Entry<String, String> entry : params.entrySet()) {//构造文本类型参数的实体数据 textEntity.append("--"); textEntity.append(BOUNDARY); textEntity.append("\r\n"); textEntity.append("Content-Disposition: form-data; name=\""+ entry.getKey() + "\"\r\n\r\n"); textEntity.append(entry.getValue()); textEntity.append("\r\n"); } //计算传输给服务器的实体数据总长度 int dataLength = textEntity.toString() .getBytes().length + fileDataLength + endline.getBytes().length; URL url = new URL(path); int port = url.getPort()==-1 ? 80 : url.getPort(); Socket socket = new Socket(InetAddress.getByName(url.getHost()), port); Log.i("hbgz", "socket connected is " + socket.isConnected()); OutputStream outStream = socket.getOutputStream(); //下面完成HTTP请求头的发送 String requestmethod = "POST "+ url.getPath()+" HTTP/1.1\r\n"; outStream.write(requestmethod.getBytes()); String accept = "Accept: image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/xaml+xml, application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*\r\n"; outStream.write(accept.getBytes()); String language = "Accept-Language: zh-CN\r\n"; outStream.write(language.getBytes()); String contenttype = "Content-Type: multipart/form-data; boundary="+ BOUNDARY+ "\r\n"; outStream.write(contenttype.getBytes()); String contentlength = "Content-Length: "+ dataLength + "\r\n"; outStream.write(contentlength.getBytes()); String alive = "Connection: Keep-Alive\r\n"; outStream.write(alive.getBytes()); String host = "Host: "+ url.getHost() +":"+ port +"\r\n"; outStream.write(host.getBytes()); //写完HTTP请求头后根据HTTP协议再写一个回车换行 outStream.write("\r\n".getBytes()); //把所有文本类型的实体数据发送出来 outStream.write(textEntity.toString().getBytes()); int lenTotal = 0; //把所有文件类型的实体数据发送出来 for(FormFile uploadFile : files){ StringBuilder fileEntity = new StringBuilder(); fileEntity.append("--"); fileEntity.append(BOUNDARY); fileEntity.append("\r\n"); fileEntity.append("Content-Disposition: form-data;name=\""+ uploadFile.getParameterName()+"\";filename=\""+ uploadFile.getFilname() + "\"\r\n"); fileEntity.append("Content-Type: "+ uploadFile.getContentType()+"\r\n\r\n"); outStream.write(fileEntity.toString().getBytes()); InputStream is = uploadFile.getInStream(); if(is!=null) { byte[] buffer = new byte[1024]; int len = 0; while((len = is.read(buffer, 0, 1024))!=-1){ outStream.write(buffer, 0, len); lenTotal += len; //每次上传的长度 Message message = new Message(); message.arg1 = 11; message.obj = lenTotal; handler.sendMessage(message); } is.close(); }else{ outStream.write(uploadFile.getData(), 0, uploadFile.getData().length); } outStream.write("\r\n".getBytes()); } //下面发送数据结束标志,表示数据已经结束 outStream.write(endline.getBytes()); BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream())); String str = ""; boolean requestCodeSuccess = false; boolean uploadSuccess = false; int indexResult = 1; while((str = reader.readLine()) != null) { Log.d("yjw", "upload--->str=" + str); if (indexResult == 1) { if (str.indexOf("200") > 0) { requestCodeSuccess = true; } } if (indexResult == 6) { if ("true".equals(str.trim())) { uploadSuccess = true; } } if (requestCodeSuccess && uploadSuccess) { outStream.flush(); if(null != socket && socket.isConnected()) { socket.shutdownInput(); socket.shutdownOutput(); } outStream.close(); reader.close(); socket.close(); return str.trim(); } else if (indexResult == 6) { outStream.flush(); if(null != socket && socket.isConnected()) { socket.shutdownInput(); socket.shutdownOutput(); } outStream.close(); reader.close(); socket.close(); return str.trim(); } ++indexResult; } outStream.flush(); if(null != socket && socket.isConnected()) { socket.shutdownInput(); socket.shutdownOutput(); } outStream.close(); reader.close(); socket.close(); return null; } catch(Exception e) { e.printStackTrace(); return null; } }
FormFile类:
/** * 上传文件 */ public class FormFile { /* 上传文件的数据 */ private byte[] data; private InputStream inStream; private File file; //上传文件大小 private int fileSize; /* 上传文件名称,可以作为服务器上显示的文件名称*/ private String filename; /* 请求参数名称 <input type="file" name="file" /> 对应的是input中的name*/ private String parameterName; /* 内容类型 */ private String contentType = "application/octet-stream"; public FormFile(String filname, File file, String parameterName, String contentType) { this.filename = filname; this.parameterName = parameterName; this.file = file; if (this.file == null) { throw new NullPointerException("file 不能为空"); } if(contentType!=null) this.contentType = contentType; } public int getFileSize() { return fileSize; } public File getFile() { return file; } public InputStream getInStream() { if (inStream != null) { try { inStream.close(); inStream = null; } catch (IOException e) { e.printStackTrace(); } } try { this.inStream = new FileInputStream(file); } catch (FileNotFoundException e) { e.printStackTrace(); } return inStream; } public byte[] getData() { return data; } public String getFilname() { return filename; } public void setFilname(String filname) { this.filename = filname; } public String getParameterName() { return parameterName; } public void setParameterName(String parameterName) { this.parameterName = parameterName; } public String getContentType() { return contentType; } public void setContentType(String contentType) { this.contentType = contentType; } }
调用方式:
/** * 上传图片到服务器,此段代码需要在新线程中运行 * * @param formFiles FormFile数组。 */ public String uploadFile(FormFile[] formFiles) { try { //请求普通信息 Map<String, String> params = new HashMap<String, String>(); params.put("method", "upload"); //如果是本机使用10.0.2.2 String result = SocketHttpRequester.post("http://10.0.2.2:8080/WebAppProject/main.do", params, formFiles,mHandler); return result; } catch (Exception e) { e.printStackTrace(); } return null; }
JAVA服务端
采用的Spring MVC的方式。在springmvc-servlet.xml文件中需要加入下面代码:<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!-- 解析request的编码 ,Default is ISO-8859-1 --> <property name="defaultEncoding"> <value>UTF-8</value> </property> </bean>
Spring MVC其他的基本配置就不在这里多说了。不清楚的可以看源码,并在网上找资料查看。
用于接收上传文件的Controller代码如下:
@Controller @RequestMapping("/main.do") public class MainController { @RequestMapping(params="method=upload") public String uploadFile(MultipartHttpServletRequest request) { System.out.println("--->uploadFile"); //1、此种方式不需要知道input的name值----下面方法2的“file”值,方法1不需要知道是多少 MultiValueMap<String,MultipartFile> multiMap = request.getMultiFileMap(); Set<String> keys = multiMap.keySet(); for (String key:keys) { List<MultipartFile> mutiFile = multiMap.get(key); writeFileToDisk(mutiFile); } //2、request.getFiles("file") //其中的"file"是<input type="file" name="file" />中的name值 //或者是android代码中HTTP协议上传的FormFile.parameterName值 //或者是android代码中的HttpClient中的multipartEntity.addPart("file",file); // List<MultipartFile> fileList = request.getFiles("file"); // writeFileToDisk(fileList); //跳转的网页,对应success.jsp return "success"; } private void writeFileToDisk(List<MultipartFile> fileList) { for (MultipartFile file : fileList) { InputStream is = null; FileOutputStream fos = null; try { System.out.println("--->"+file.getSize()); is = file.getInputStream(); fos = new FileOutputStream("D:/a/"+System.currentTimeMillis()+".png"); byte[] buffer = new byte[1024]; int len=0; while ((len = is.read(buffer)) != -1) { fos.write(buffer, 0, len); } fos.flush(); } catch (IOException e) { e.printStackTrace(); } finally { try { if (fos != null) { fos.close(); } if (is != null) { is.close(); } } catch (IOException e) { e.printStackTrace(); } } } } }
附上JSP上传的代码(源码中的upload.jsp):
<form action="main.do?method=upload" method="post" enctype="multipart/form-data">
Upload1:<input type="file" name="file" /><br/>
Upload2:<input type="file" name="file" /><br/>
<input type="submit" title="upload" />
</form>
以上需要注意的是android客户段代码中什么属性值和JSP中的参数对应-----这个在代码注释中有强调。
源码地址:android批量文件上传Demo
Demo中是从相册选择图片上传,因为各个版本的android系统原因,在打开相册获取图片的方法写的比较全(此处代码也有点多)。需要的也可以直接拷贝使用。
相关文章推荐
- 基于JAVA中Jersey处理Http协议中的Multipart的详解
- Spring整合Dwr,Cannot locate BeanDefinitionParser for element [annotation-scan]
- HTTP协议理解与应用总结
- spring3 MVC手工搭建Spring3项目demo
- HTTP协议详解
- 协议-HTTP协议详解
- spring mvc 开发需要的jar包的用途详解
- 基于注解的 Spring MVC 简单入门-网摘
- [MVC] 深入浅出Spring MVC
- HTTP协议详解(转帖:非常经典)
- JavaWEB.HTTP协议(基础)
- 浅谈HTTP中Get与Post的区别(转)
- 网络知识---HTTP protocol
- 用户登录具体实现与安全防范
- 用户登录具体实现与安全防范
- http协议常用请求头与响应头
- GET和POST乱码问题剖析
- (转)HttpClient 4.3.6 教程 前言 【翻译】
- Spring MVC 为例,从前台—>后台—>前台的编解码过程及出现乱码的案例
- HTTP 协议中的POST 与 GET请求 [原作者分析的挺好]