一:实现原理
最近在做AndroID客户端的应用开发,涉及到要把图片上传到后台服务器中,自己选择了做Spring3 MVC http API作为后台上传接口,androID客户端我选择用httpURLConnection来通过form提交文件数据实现上传功能,本来想网上搜搜拷贝一下改改代码就好啦,发现根本没有现成的例子,多数的例子都是基于httpClIEnt的或者是基于Base64编码以后作为字符串来传输图像数据,于是我不得不自己动手,参考了网上一些资料,最终实现基于httpURLConnection上传文件的androID客户端代码,废话少说,其实基于httpURLConnection实现文件上传最关键的在于要熟悉http协议相关知识,知道MIME文件块在http协议中的格式表示,基本的传输数据格式如下:
其中boundary表示form的边界,只要按照格式把内容字节数写到httpURLConnection的对象输出流中,服务器端的Spring Controller 就会自动响应接受,跟从浏览器页面上上传文件是一样的。
服务器端http API, 我是基于Spring3 MVC实现的Controller,代码如下:
@RequestMapPing(value = "/uploadMyImage/{token}",method = RequestMethod.POST) public @ResponseBody String getUploadfile(httpServletRequest request,httpServletResponse response,@PathVariable String token) { logger.info("spring3 MVC upload file with Multipart form"); logger.info("servlet context path : " + request.getSession().getServletContext().getRealPath("/")); UserDto profileDto = userService.getUserByToken(token); String imgUUID = ""; try { if (request instanceof MultiparthttpServletRequest && profileDto.getToken() != null) { MultiparthttpServletRequest multipartRequest = (MultiparthttpServletRequest) request; logger.info("spring3 MVC upload file with Multipart form"); // does not work,oh my god!! multipartfile file = multipartRequest.getfiles("myfile").get(0); inputStream input = file.getinputStream(); long fileSize = file.getSize(); BufferedImage image = ImageIO.read(input); // create data transfer object ImageDto dto = new ImageDto(); dto.setCreateDate(new Date()); dto.setfilename(file.getoriginalfilename()); dto.setimage(image); dto.setCreator(profileDto.getUsername()); dto.setfileSize(fileSize); dto.setType(ImageAttachmentType.CLIENT_TYPE.getTitle()); dto.setUuID(UUID.randomUUID().toString()); /// save to DB imgUUID = imageService.createImage(dto); input.close(); } } catch (Exception e) { e.printstacktrace(); logger.error("upload image error",e); } return imgUUID; }
AndroID客户端基于httpURLConnection实现上传的代码,我把它封装成一个单独的类文件,这样大家可以直接使用,只要传入上传的URL等参数即可。代码如下:
package com.demo.http; import java.io.BufferedinputStream; import java.io.DataOutputStream; import java.io.file; import java.io.fileinputStream; import java.io.IOException; import java.io.inputStream; import java.net.httpURLConnection; import java.net.URL; import java.util.Random; import androID.os.Handler; import androID.util.Base64; import androID.util.Log; public class UploadImageTask implements APIURLConstants { private String requestURL = DOMAIN_ADDRESS + UPLOAD_DESIGN_IMAGE_URL; // default private final String CRLF = "\r\n"; private Handler handler; private String token; public UploadImageTask(String token,Handler handler) { this.handler = handler; this.token = token; } public String execute(file...files) { inputStream inputStream = null; httpURLConnection urlConnection = null; fileinputStream fileinput = null; DataOutputStream requestStream = null; handler.sendEmptyMessage(50); try { // open connection URL url = new URL(requestURL.replace("{token}",this.token)); urlConnection = (httpURLConnection) url.openConnection(); // create random boundary Random random = new Random(); byte[] randomBytes = new byte[16]; random.nextBytes(randomBytes); String boundary = Base64.encodetoString(randomBytes,Base64.NO_WRAP); /* for POST request */ urlConnection.setDoOutput(true); urlConnection.setDoinput(true); urlConnection.setUseCaches(false); urlConnection.setRequestMethod("POST"); long size = (files[0].length() / 1024); if(size >= 1000) { handler.sendEmptyMessage(-150); return "error"; } // 构建Entity form urlConnection.setRequestProperty("Connection","Keep-Alive"); urlConnection.setRequestProperty("Content-Type","multipart/form-data;boundary=" + boundary); urlConnection.setRequestProperty("Cache-Control","no-cache"); // never try to chunked mode,you need to set a lot of things // if(size > 400) { // urlConnection.setChunkedStreamingMode(0); // } // else { // urlConnection.setFixedLengthStreamingMode((int)files[0].length()); // } // end comment by zhigang on 2016-01-19 /* upload file stream */ fileinput = new fileinputStream(files[0]); requestStream = new DataOutputStream(urlConnection.getoutputStream()); String nikename = "myfile"; requestStream = new DataOutputStream(urlConnection.getoutputStream()); requestStream.writeBytes("--" + boundary + CRLF); requestStream.writeBytes("Content-disposition: form-data; name=\"" + nikename + "\"; filename=\"" + files[0].getname() + "\""+ CRLF); requestStream.writeBytes("Content-Type: " + getMIMEType(files[0]) + CRLF); requestStream.writeBytes(CRLF); // 写图像字节内容 int bytesRead; byte[] buffer = new byte[8192]; handler.sendEmptyMessage(50); while((bytesRead = fileinput.read(buffer)) != -1) { requestStream.write(buffer,bytesRead); } requestStream.flush(); requestStream.writeBytes(CRLF); requestStream.flush(); requestStream.writeBytes("--" + boundary + "--" + CRLF); requestStream.flush(); fileinput.close(); // try to get response int statusCode = urlConnection.getResponseCode(); if (statusCode == 200) { inputStream = new BufferedinputStream(urlConnection.getinputStream()); String imageuuID = httpUtil.convertinputStreamToString(inputStream); Log.i("image-uuID","uploaded image uuID : " + imageuuID); handler.sendEmptyMessage(50); return imageuuID; } } catch (Exception e) { e.printstacktrace(); } finally { if (inputStream != null) { try { inputStream.close(); } catch (IOException e) { e.printstacktrace(); } } if(requestStream != null) { try { requestStream.close(); } catch (IOException e) { e.printstacktrace(); } } if(fileinput != null) { try { fileinput.close(); } catch (IOException e) { e.printstacktrace(); } } if (urlConnection != null) { urlConnection.disconnect(); } } handler.sendEmptyMessage(50); return null; } private String getMIMEType(file file) { String filename = file.getname(); if(filename.endsWith("png") || filename.endsWith("PNG")) { return "image/png"; } else { return "image/jpg"; } } }
经过本人测试,效果杠杠的!!所以请忘记httpClIEnt这个东西,androID开发再也不需要它了。
总结以上是内存溢出为你收集整理的Android程序开发通过HttpURLConnection上传文件到服务器全部内容,希望文章能够帮你解决Android程序开发通过HttpURLConnection上传文件到服务器所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)