Android程序开发通过HttpURLConnection上传文件到服务器


 一:实现原理

最近在做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, 0, 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开发再也不需要它了。



相关阅读:
PHP中类的继承和用法实例分析
各种AJAX方法的使用比较详解
win7升级win8系统后鼠标间歇性失灵如何解决
php微信支付之APP支付方法
win10预览版10061系统主题颜色怎么更改
Jquery实现仿腾讯微博发表广播
PHP 抽象方法与抽象类abstract关键字介绍及应用
使用配置类定义Codeigniter全局变量
WordPress主题制作之模板文件的引入方法
如何解决mysqlimport: Error: 13, Can't get stat of 的问题
快速解决owin返回json字符串多带了双引号"多了重string转义字符串
JavaWeb开发入门第一篇必备知识讲解
php使用strip_tags()去除html标签仍有空白的解决方法
HTML5之SVG 2D入门7—SVG元素的重用与引用
快速导航
PHP MySQL HTML CSS JavaScript MSSQL AJAX .NET JSP Linux Mac ASP 服务器 SQL jQuery C# C++ java Android IOS oracle MongoDB SQLite wamp 交通频道 作文范文 校园文体活动策划书 时间的手 欣赏的近义词_欣赏的近义词是什么 2015先进事迹活动情况的汇报 游中华恐龙园作文700字 湘流应识九歌心——《九歌》500字 父亲的坐骑 最新公司发放高温补贴通知 最伤感最凄美的爱情日志语录 这天我回家晚了作文500字 望着你我无语 一些对自己讲的话 我学古筝作文500字 难以割舍的新闻情结 我的小表哥作文600字 想抱着你哭,为你收住漂泊之步 开创流动人口计划生育工作新局面讲话 幽默晚安短信 入党介绍人的主要职责有哪些 商场服装销售工作计划 城建合理布局推进规划工作发展水平调研建议 我的课余生活作文400字 创先争优活动宣传工作方案 团圆饭作文 达尔文观察趣事作文300字 展开微笑的翅膀作文500字 我喜欢的小闹钟作文250字 初中初三作文800字:黛染柳眉,玉碧添香 2014最新餐馆服务员实习报告范文 德国之旅(9)---室友从床上掉下来 《平凡的世界》读后感——我是平凡的世界的一粒沙 桐柏宫作文 写在党的生日--无悔的青春无悔的誓言 秦皇岛之旅日记两篇1200字 捉蝌蚪作文 别开生面的游泳比赛作文800字 小学五年级作文500字:载着梦想一起飞 小学二年级作文350字:假如我遇到了外星人——段昶君 畅想未来城市的美好 透着暗香的花,无人知晓 校园周边饭店餐饮创业计划书范文 我喜欢春天里的趣事200字 2015热爱学校的演讲稿 大翅膀 幼儿园大班数学教案:小螃蟹吐泡泡 在心境里织一面网 人生无从分割的际遇 黄瑞槐:心悸遥远 小学读后感 字体的演变一般是缓慢的,作文100字

Copyright © 2016 phpStudy |