当前位置: 移动技术网 > IT编程>移动开发>Android > Android程序开发通过HttpURLConnection上传文件到服务器

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

2019年07月24日  | 移动技术网IT编程  | 我要评论

马谡街亭败给谁,替身庶女爱上帅总裁,e200

 一:实现原理

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

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网