昨天说老师说了android的网络存储,对协议有了一个更深的理解。

数据上传到网络,尽管 b/s 和c/s的架构不一样,但是它们还是能上传数据到网络,因为都遵循协议的规范,c/s存储数据到网络,思想模仿浏览器发送数据服务器的请求头信息,在底层通过android提供的socket去链接网络,发送相应的数据,如果协议没拼接错误的话,能获得正确的相应码,并作出相应的操作。

总的来说,其实android网络存储重点还是对协议的拼接的,在此过程中必须静下心来才能做好拼接操作。

b/s通过访问服务器的网络段的请求头数据如下:·

POST /ownUploadServer/doupload.action HTTP/1.1Host: localhostUser-Agent: Mozilla/5.0 (Windows NT 6.1; rv:35.0) Gecko/20100101 Firefox/35.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3Accept-Encoding: gzip, deflateReferer: http://localhost/ownUploadServer/Cookie: JSESSIONID=F0EE9F4C17CB90FCADB60AC34B6AB871; CNZZDATA1000112112=1371504373-1430749960-%7C1430817053; 
Hm_lvt_b24307b87f33ce3e55789d58670dbbd5=1430809410; Hm_lvt_21a80e96f6b0bb699ad5f04db22194a4=1430809411; bdshare_firstime=1431935932462Connection: keep-alive
通过观察得知,请求头信息比较重要的是:
POST /ownUploadServer/doupload.action HTTP/1.1 ,它包括了请求的方式,访问的资源地址,协议的版本。
Host: localhost ip信息
   
Connection: keep-alive 保持连接
传过去的参数:
-----------------------------28332323972849 
Content-Disposition: form-data; name="picdesc" 
12 
-----------------------------28332323972849 
Content-Disposition: form-data; name="size" 
23 
-----------------------------28332323972849 
Content-Disposition: form-data; name="ptype" 人æ 
-----------------------------28332323972849 
Content-Disposition: form-data; name="pic1"; filename="2.png" 
Content-Type: image/pngxxxx-----------------------------28332323972849-- 
   

这里要注意的是协议的拼接非常的严格,一个地方错都会导致程序的崩溃的。

服务器端使用tomcat,客户端是addroid平台,下面实现数据存储:

客户端代码:上传的bean类

public class UploadFile implements Serializable{private static final long serialVersionUID = 3445579255260832749L;/** *文件的内容 */private byte[] data;/** * 可以通过这个流读数据 */private InputStream inStream;private File file;/** * 文件名 */private String filename;/** * 文件类型 */private String contentType="application/octet-stream";private String parameterName;public UploadFile(byte[] data, String filename, String contentType,String parameterName) {super();this.data = data;this.filename = filename;this.contentType = contentType;this.parameterName = parameterName;}public UploadFile(File file, String filename, String contentType,String parameterName) {super();this.file = file;this.filename = filename;this.contentType = contentType;this.parameterName = parameterName;try {this.inStream=new FileInputStream(this.file);} catch (FileNotFoundException e) {e.printStackTrace();}}public byte[] getData() {return data;}public void setData(byte[] data) {this.data = data;}public InputStream getInStream() {return inStream;}public void setInStream(InputStream inStream) {this.inStream = inStream;}public File getFile() {return file;}public void setFile(File file) {this.file = file;}public String getFilename() {return filename;}public void setFilename(String filename) {this.filename = filename;}public String getContentType() {return contentType;}public void setContentType(String contentType) {this.contentType = contentType;}public String getParameterName() {return parameterName;}public void setParameterName(String parameterName) {this.parameterName = parameterName;}}
上传帮助类:

package com.yc.utils;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.InetAddress;import java.net.Socket;import java.net.URL;import java.net.UnknownHostException;import java.util.List;import java.util.Map;import com.yc.bean.UploadFile;;public class WebUtil {/** * 文件上传 * @param address * @param params * @param uploadFiles * @throws IOException  * @throws UnknownHostException  */public String postFileToServer(String address,Map params,List uploadFiles) throws UnknownHostException, IOException{final String BOUNDARY="---------------------------1123240313494";final String SEPARATOR="--"+BOUNDARY;final String BREAKLINE="\r\n";final String ENDLINE=BREAKLINE+SEPARATOR+"--";long totalLength=0;long fileTotalLength=0;//计算uploadFiles部分的总长度if(uploadFiles!=null&&uploadFiles.size()>0){for(UploadFile uf:uploadFiles){StringBuffer sb=new StringBuffer();sb.append(SEPARATOR);sb.append(BREAKLINE);sb.append("Content-Disposition: form-data; name=\""+uf.getParameterName()+"\"; filename=\""+ uf.getFilename()+"\"");sb.append(BREAKLINE);sb.append("Content-Type: "+uf.getContentType());sb.append(BREAKLINE).append(BREAKLINE);//因为图片数据的后面也要加入一个\r\nsb.append(BREAKLINE);fileTotalLength+=sb.toString().getBytes().length;//计算这个uf的真实长度if(uf.getInStream()==null){fileTotalLength+=uf.getData().length;}else{fileTotalLength+=uf.getFile().length();}}}//计算文本参数部分的总长度StringBuffer textEntity=new StringBuffer();if(params!=null&¶ms.size()>0){for(Map.Entry entry:params.entrySet()){textEntity.append(SEPARATOR);textEntity.append(BREAKLINE);textEntity.append("Content-Disposition: form-data; name=\""+entry.getKey()+"\"");textEntity.append(BREAKLINE);textEntity.append(BREAKLINE);textEntity.append(entry.getValue());textEntity.append(BREAKLINE);}}//总长度totalLength=fileTotalLength+textEntity.toString().getBytes().length+ENDLINE.getBytes().length;//访问网络,发送协议URL url=new URL(address);//取出端口int port=url.getPort()==-1?80:url.getPort();//创建socket,以socket套接字访问服务器Socket s=new Socket(InetAddress.getByName(url.getHost()),port);//取出输入流OutputStream oos=s.getOutputStream();//拼接请求头String requestCommand="POST "+url.getPath()+" HTTP/1.1"+BREAKLINE;oos.write(requestCommand.getBytes());String hostword="Host: "+url.getHost()+BREAKLINE;oos.write(hostword.getBytes());String connectionword="Connection: keep-alive"+BREAKLINE;oos.write(connectionword.getBytes());String contenttypeword="Content-Type: multipart/form-data; boundary="+BOUNDARY+BREAKLINE;oos.write(contenttypeword.getBytes());String contentlength="Content-Length: "+totalLength+BREAKLINE;oos.write(contentlength.getBytes());//请求头与请求实体间的空行oos.write(BREAKLINE.getBytes());//发出文本实体oos.write(textEntity.toString().getBytes());//发出文件//计算出uploadFiles部分的总长度if(uploadFiles!=null&&uploadFiles.size()>0){for(UploadFile uf:uploadFiles){StringBuffer sb=new StringBuffer();sb.append(SEPARATOR);sb.append(BREAKLINE);sb.append("Content-Disposition: form-data; name=\""+uf.getParameterName()+"\"; filename=\""+ uf.getFilename()+"\"");sb.append(BREAKLINE);sb.append("Content-Type: "+uf.getContentType());sb.append(BREAKLINE).append(BREAKLINE);//以上是这个文件的文本信息部分oos.write(sb.toString().getBytes());if(uf.getInStream()!=null){//以流的形式先读,再用oos写byte[] buffer=new byte[1024];int length=-1;while((length=uf.getInStream().read(buffer,0,buffer.length))!=-1){oos.write(buffer,0,length);}}else{oos.write(uf.getData(),0,uf.getData().length);}oos.write(BREAKLINE.getBytes());oos.flush();}}//还有一个结束行oos.write(ENDLINE.getBytes());oos.flush();//接收服务器的回应InputStream iis=s.getInputStream();String result=new String();int len=-1;byte[] b=new byte[1024];while((len=iis.read(b,0,b.length))!=-1){result+=new String(b,0,len);}oos.close();iis.close();s.close();return result;}}

然后在主界面调用的如下:这个要注意的是android在高版本的时候在上传文件到网络的时候,必须要开启新的线程而不能再主线程中操作。

我用的是handler类通过消息机制操作线程,也是可以通过AsyncTask操作。

线程代码如下:

btn4.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View arg0) {new Thread(new Runnable() {@Overridepublic void run() {Mapparams=new HashMap();Person p =(Person)FilesUtils.getObjectFromFile("xiaofeng", MainActivity2.this);params.put("name", p.getName());params.put("age", p.getAge()+"");params.put("sex", p.getSex());ListuploadFiles=new ArrayList();File headFile=new File(p.getHeadpic());String filename=headFile.getName();uploadFiles.add(new UploadFile(headFile, filename, "image/jpeg", "headpic"));WebUtil wu=new WebUtil();try {String responseprotocol=wu.postFileToServer("http://211.69.255.66/ownUploadServer/doupload.action", params, uploadFiles);Message m=new Message();m.what=1;m.obj=responseprotocol;handler.sendMessage(m);} catch (Exception e) {e.printStackTrace();}}}).start();
Hannler的实例如下:

private Handler handler=new Handler(){public void handleMessage(android.os.Message msg) {switch(msg.what){case 1:String response=(String) msg.obj;if(response.indexOf("200")>0){Toast.makeText(MainActivity2.this, "上传云端成功", 3000).show();}}}};
值得一提的是:android在发送数据到服务器的时候,一定不能写localhost,因为localhost已经被android模拟器占用了,只能用ip地址,而且如果是真机测试的话,还要保证手机的网段和电脑的网段一致,并且关闭防火墙。才能测试成功。。


通过学习android的网络存储,对协议有更深的了解了,加油






更多相关文章

  1. Android上实现柱状图表
  2. Android中AsyncTask的简单用法及实现网络图片下载的实例
  3. 搭建Android应用程序的服务器
  4. 一起来开发Android的天气软件(三)——使用Volley实现网络通信
  5. Android上如何正确实现程序的联网,事关WIFI/CMWAP/CMNET
  6. Android之内存缓存——LruCache的使用及原理
  7. [置顶] 【Android】开源 闲暇(Leisure) 阅读类应用的开发
  8. android SQLite存储简单范例+详细注释(增删查改)
  9. Android(安卓)应用开发的耗电量控制

随机推荐

  1. 谷歌Android篡改Linux内核的真相
  2. android投屏和媒体共享相关 && audio foc
  3. Android系统信息(内存、cpu、sd卡、电量、
  4. AlarmManagerService(一)
  5. 移植android ndk c++各种兼容性问题
  6. 【059】分享我的 Android(安卓)应用
  7. Android(安卓)定时器真机测试
  8. 25个你应该阅读的Android网站
  9. IPC与Binder,Binder线程池,AIDL demo - And
  10. 关于android WebViewClient和WebChromeCl