Android基于Http协议实现文件上传功能的方法
程序员文章站
2024-03-05 08:16:24
本文实例讲述了android基于http协议实现文件上传功能的方法。分享给大家供大家参考,具体如下:
注意一般使用http协议上传的文件都比较小,一般是小于2m
这里示...
本文实例讲述了android基于http协议实现文件上传功能的方法。分享给大家供大家参考,具体如下:
注意一般使用http协议上传的文件都比较小,一般是小于2m
这里示例是上传一个小的mp3文件
1.主activity:mainactivity.java
public class mainactivity extends activity { private static final string tag = "mainactivity"; private edittext timelengthtext; private edittext titletext; private edittext videotext; @override public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.main); //提交上传按钮 button button = (button) this.findviewbyid(r.id.button); timelengthtext = (edittext) this.findviewbyid(r.id.timelength); videotext = (edittext) this.findviewbyid(r.id.video); titletext = (edittext) this.findviewbyid(r.id.title); button.setonclicklistener(new view.onclicklistener() { @override public void onclick(view v) { string title = titletext.gettext().tostring(); string timelength = timelengthtext.gettext().tostring(); map<string, string> params = new hashmap<string, string>(); params.put("method", "save"); params.put("title", title); params.put("timelength", timelength); try { //得到sdcard的目录 file uploadfile = new file(environment.getexternalstoragedirectory(), videotext.gettext().tostring()); //上传音频文件 formfile formfile = new formfile("02.mp3", uploadfile, "video", "audio/mpeg"); sockethttprequester.post("http://192.168.1.100:8080/videoweb/video/manage.do", params, formfile); toast.maketext(mainactivity.this, r.string.success, 1).show(); } catch (exception e) { toast.maketext(mainactivity.this, r.string.error, 1).show(); log.e(tag, e.tostring()); } } }); } }
2.上传工具类,注意里面构造协议字符串需要根据不同的提交表单来处理
public class sockethttprequester { /** * 发送xml数据 * @param path 请求地址 * @param xml xml数据 * @param encoding 编码 * @return * @throws exception */ public static byte[] postxml(string path, string xml, string encoding) throws exception{ byte[] data = xml.getbytes(encoding); url url = new url(path); httpurlconnection conn = (httpurlconnection)url.openconnection(); conn.setrequestmethod("post"); conn.setdooutput(true); conn.setrequestproperty("content-type", "text/xml; charset="+ encoding); conn.setrequestproperty("content-length", string.valueof(data.length)); conn.setconnecttimeout(5 * 1000); outputstream outstream = conn.getoutputstream(); outstream.write(data); outstream.flush(); outstream.close(); if(conn.getresponsecode()==200){ return readstream(conn.getinputstream()); } return null; } /** * 直接通过http协议提交数据到服务器,实现如下面表单提交功能: * <form method=post action="http://192.168.0.200:8080/ssi/fileload/test.do" enctype="multipart/form-data"> <input type="text" name="name"> <input type="text" name="id"> <input type="file" name="imagefile"/> <input type="file" name="zip"/> </form> * @param path 上传路径(注:避免使用localhost或127.0.0.1这样的路径测试, * 因为它会指向手机模拟器,你可以使用http://www.baidu.com或http://192.168.1.10:8080这样的路径测试) * @param params 请求参数 key为参数名,value为参数值 * @param file 上传文件 */ public static boolean post(string path, map<string, string> params, formfile[] files) throws exception { //数据分隔线 final string boundary = "---------------------------7da2137580612"; //数据结束标志"---------------------------7da2137580612--" final string endline = "--" + boundary + "--/r/n"; //下面两个for循环都是为了得到数据长度参数,依据表单的类型而定 //首先得到文件类型数据的总长度(包括文件分割线) 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){ filedatalength += uploadfile.getfile().length(); }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 socket = new socket(inetaddress.getbyname(url.gethost()), port); //获得一个输出流(从android流到web) outputstream outstream = socket.getoutputstream(); //下面完成http请求头的发送 string requestmethod = "post "+ url.getpath()+" http/1.1/r/n"; outstream.write(requestmethod.getbytes()); //构建accept 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()); //构建language string language = "accept-language: zh-cn/r/n"; outstream.write(language.getbytes()); //构建contenttype string contenttype = "content-type: multipart/form-data; boundary="+ boundary+ "/r/n"; outstream.write(contenttype.getbytes()); //构建contentlength string contentlength = "content-length: "+ datalength + "/r/n"; outstream.write(contentlength.getbytes()); //构建alive string alive = "connection: keep-alive/r/n"; outstream.write(alive.getbytes()); //构建host string host = "host: "+ url.gethost() +":"+ port +"/r/n"; outstream.write(host.getbytes()); //写完http请求头后根据http协议再写一个回车换行 outstream.write("/r/n".getbytes()); //把所有文本类型的实体数据发送出来 outstream.write(textentity.tostring().getbytes()); //把所有文件类型的实体数据发送出来 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()); //边读边写 if(uploadfile.getinstream()!=null) { byte[] buffer = new byte[1024]; int len = 0; while((len = uploadfile.getinstream().read(buffer, 0, 1024))!=-1) { outstream.write(buffer, 0, len); } uploadfile.getinstream().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())); //读取web服务器返回的数据,判断请求码是否为200,如果不是200,代表请求失败 if(reader.readline().indexof("200")==-1) { return false; } outstream.flush(); outstream.close(); reader.close(); socket.close(); return true; } /** * 提交数据到服务器 * @param path 上传路径(注:避免使用localhost或127.0.0.1这样的路径测试,因为它会指向手机模拟器,你可以使用http://www.baidu.com或http://192.168.1.10:8080这样的路径测试) * @param params 请求参数 key为参数名,value为参数值 * @param file 上传文件 */ public static boolean post(string path, map<string, string> params, formfile file) throws exception { return post(path, params, new formfile[]{file}); } /** * 提交数据到服务器 * @param path 上传路径(注:避免使用localhost或127.0.0.1这样的路径测试,因为它会指向手机模拟器,你可以使用http://www.baidu.com或http://192.168.1.10:8080这样的路径测试) * @param params 请求参数 key为参数名,value为参数值 * @param encode 编码 */ public static byte[] postfromhttpclient(string path, map<string, string> params, string encode) throws exception { //用于存放请求参数 list<namevaluepair> formparams = new arraylist<namevaluepair>(); for(map.entry<string, string> entry : params.entryset()) { formparams.add(new basicnamevaluepair(entry.getkey(), entry.getvalue())); } urlencodedformentity entity = new urlencodedformentity(formparams, encode); httppost httppost = new httppost(path); httppost.setentity(entity); //看作是浏览器 httpclient httpclient = new defaulthttpclient(); //发送post请求 httpresponse response = httpclient.execute(httppost); return readstream(response.getentity().getcontent()); } /** * 发送请求 * @param path 请求路径 * @param params 请求参数 key为参数名称 value为参数值 * @param encode 请求参数的编码 */ public static byte[] post(string path, map<string, string> params, string encode) throws exception { //string params = "method=save&name="+ urlencoder.encode("老毕", "utf-8")+ "&age=28&";//需要发送的参数 stringbuilder parambuilder = new stringbuilder(""); if(params!=null && !params.isempty()) { for(map.entry<string, string> entry : params.entryset()) { parambuilder.append(entry.getkey()).append("=") .append(urlencoder.encode(entry.getvalue(), encode)).append("&"); } parambuilder.deletecharat(parambuilder.length()-1); } byte[] data = parambuilder.tostring().getbytes(); url url = new url(path); httpurlconnection conn = (httpurlconnection)url.openconnection(); //设置允许对外发送请求参数 conn.setdooutput(true); //设置不进行缓存 conn.setusecaches(false); conn.setconnecttimeout(5 * 1000); conn.setrequestmethod("post"); //下面设置http请求头 conn.setrequestproperty("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, */*"); conn.setrequestproperty("accept-language", "zh-cn"); conn.setrequestproperty("user-agent", "mozilla/4.0 (compatible; msie 8.0; windows nt 5.2; trident/4.0; .net clr 1.1.4322; .net clr 2.0.50727; .net clr 3.0.04506.30; .net clr 3.0.4506.2152; .net clr 3.5.30729)"); conn.setrequestproperty("content-type", "application/x-www-form-urlencoded"); conn.setrequestproperty("content-length", string.valueof(data.length)); conn.setrequestproperty("connection", "keep-alive"); //发送参数 dataoutputstream outstream = new dataoutputstream(conn.getoutputstream()); outstream.write(data);//把参数发送出去 outstream.flush(); outstream.close(); if(conn.getresponsecode()==200) { return readstream(conn.getinputstream()); } return null; } /** * 读取流 * @param instream * @return 字节数组 * @throws exception */ public static byte[] readstream(inputstream instream) throws exception { bytearrayoutputstream outsteam = new bytearrayoutputstream(); byte[] buffer = new byte[1024]; int len = -1; while( (len=instream.read(buffer)) != -1) { outsteam.write(buffer, 0, len); } outsteam.close(); instream.close(); return outsteam.tobytearray(); } } public class streamtool { /** * 从输入流读取数据 * @param instream * @return * @throws exception */ public static byte[] readinputstream(inputstream instream) throws exception{ bytearrayoutputstream outsteam = new bytearrayoutputstream(); byte[] buffer = new byte[1024]; int len = 0; while( (len = instream.read(buffer)) !=-1 ){ outsteam.write(buffer, 0, len); } outsteam.close(); instream.close(); return outsteam.tobytearray(); } } /** * 使用javabean封装上传文件数据 * */ public class formfile { //上传文件的数据 private byte[] data; private inputstream instream; private file file; //文件名称 private string filname; //请求参数名称 private string parametername; //内容类型 private string contenttype = "application/octet-stream"; /** * 上传小文件,把文件数据先读入内存 * @param filname * @param data * @param parametername * @param contenttype */ public formfile(string filname, byte[] data, string parametername, string contenttype) { this.data = data; this.filname = filname; this.parametername = parametername; if(contenttype!=null) this.contenttype = contenttype; } /** * 上传大文件,一边读文件数据一边上传 * @param filname * @param file * @param parametername * @param contenttype */ public formfile(string filname, file file, string parametername, string contenttype) { this.filname = filname; this.parametername = parametername; this.file = file; try { this.instream = new fileinputstream(file); } catch (filenotfoundexception e) { e.printstacktrace(); } if(contenttype!=null) this.contenttype = contenttype; } public file getfile() { return file; } public inputstream getinstream() { return instream; } public byte[] getdata() { return data; } public string getfilname() { return filname; } public void setfilname(string filname) { this.filname = 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; } }
更多关于android相关内容感兴趣的读者可查看本站专题:《android文件操作技巧汇总》、《android操作sqlite数据库技巧总结》、《android操作json格式数据技巧总结》、《android数据库操作技巧总结》、《android编程之activity操作技巧总结》、《android编程开发之sd卡操作方法汇总》、《android开发入门与进阶教程》、《android资源操作技巧汇总》、《android视图view技巧总结》及《android控件用法总结》
希望本文所述对大家android程序设计有所帮助。