本文所要讲的是Android断点续传的内容,以实例的形式进行了详细介绍。

       一、断点续传的原理

       其实断点续传的原理很简单,就是在http的请求上和一般的下载有所不同而已。

       打个比方,浏览器请求服务器上的一个文时,所发出的请求如下:

       假设服务器域名为www.jizhuomi.com/android,文件名为down.zip。

get /down.zip http/1.1
accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-
excel, application/msword, application/vnd.ms-powerpoint, */*
accept-language: zh-cn
accept-encoding: gzip, deflate
user-agent: mozilla/4.0 (compatible; msie 5.01; windows nt 5.0)
connection: keep-alive

       服务器收到请求后,按要求寻找请求的文件,提取文件的信息,然后返回给浏览器,返回信息如下:

200
content-length=106786028
accept-ranges=bytes
date=mon, 30 apr 2001 12:56:11 gmt
etag=w/"02ca57e173c11:95b"
content-type=application/octet-stream
server=microsoft-iis/5.0
last-modified=mon, 30 apr 2001 12:56:11 gmt

       所谓断点续传,也就是要从文件已经下载的地方开始继续下载。所以在客户端浏览器传给web服务器的时候要多加一条信息--从哪里开始。

       下面是用自己编的一个“浏览器”来传递请求信息给web服务器,要求从2000070字节开始。

get /down.zip http/1.0
user-agent: netfox
range: bytes=2000070-
accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2

       仔细看一下就会发现多了一行 range: bytes=2000070-

       这一行的意思就是告诉服务器down.zip这个文件从2000070字节开始传,前面的字节不用传了。

       服务器收到这个请求以后,返回的信息如下:

206
content-length=106786028
content-range=bytes 2000070-106786027/106786028
date=mon, 30 apr 2001 12:55:20 gmt
etag=w/"02ca57e173c11:95b"
content-type=application/octet-stream
server=microsoft-iis/5.0
last-modified=mon, 30 apr 2001 12:55:20 gmt

       和前面服务器返回的信息比较一下,就会发现增加了一行:

content-range=bytes 2000070-106786027/106786028

       返回的代码也改为206了,而不再是200了。

       知道了以上原理,就可以进行断点续传的编程了。

       二、java实现断点续传的关键几点

       用什么方法实现提交range: bytes=2000070-?

       当然用最原始的socket是肯定能完成的,不过那样太费事了,其实java的net包中提供了这种功能。代码如下:

Java代码

url url = new url("http://www.jizhuomi.com/android/down.zip");  httpurlconnection httpconnection = (httpurlconnection)url.openconnection();  //设置user-agent  httpconnection.setrequestproperty("user-agent","netfox");  //设置断点续传的开始位置  httpconnection.setrequestproperty("range","bytes=2000070");  //获得输入流  inputstream input = httpconnection.getinputstream();     从输入流中取出的字节流就是down.zip文件从2000070开始的字节流。    大家看,其实断点续传用java实现起来还是很简单的吧。    接下来要做的事就是怎么保存获得的流到文件中去了。    保存文件采用的方法:我采用的是io包中的randaccessfile类。    操作相当简单,假设从2000070处开始保存文件,代码如下:Java代码randomaccess osavedfile = new randomaccessfile("down.zip","rw");  long npos = 2000070;  //定位文件指针到npos位置  osavedfile.seek(npos);  byte[] b = new byte[1024];  int nread;  //从输入流中读入字节流,然后写到文件中  while((nread=input.read(b,0,1024)) > 0)  {    osavedfile.write(b,0,nread);  }     怎么样,也很简单吧。    接下来要做的就是整合成一个完整的程序了。包括一系列的线程控制等等。    三、断点续传内核的实现    主要用了6个类,包括一个测试类。    sitefilefetch.java负责整个文件的抓取,控制内部线程(filesplitterfetch类)。    filesplitterfetch.java负责部分文件的抓取。    fileaccess.java负责文件的存储。    siteinfobean.java要抓取的文件的信息,如文件保存的目录,名字,抓取文件的url等。    utility.java工具类,放一些简单的方法。    testmethod.java测试类。    四、实例源码    下面是源程序:Java代码/* **sitefilefetch.java */ package netfox;  import java.io.*;  import java.net.*;    public class sitefilefetch extends thread {    siteinfobean siteinfobean = null; //文件信息bean  long[] nstartpos; //开始位置  long[] nendpos; //结束位置  filesplitterfetch[] filesplitterfetch; //子线程对象  long nfilelength; //文件长度  boolean bfirst = true; //是否第一次取文件  boolean bstop = false; //停止标志  file tmpfile; //文件下载的临时信息  dataoutputstream output; //输出到文件的输出流   public sitefilefetch(siteinfobean bean) throws ioexception  {  siteinfobean = bean;  //tmpfile = file.createtempfile ("zhong","1111",new file(bean.getsfilepath()));  tmpfile = new file(bean.getsfilepath()+file.separator + bean.getsfilename()+".info");  if(tmpfile.exists ())  {  bfirst = false;  read_npos();  }  else {  nstartpos = new long[bean.getnsplitter()];  nendpos = new long[bean.getnsplitter()];  }   }    public void run()  {  //获得文件长度  //分割文件  //实例filesplitterfetch  //启动filesplitterfetch线程  //等待子线程返回  try{  if(bfirst)  {  nfilelength = getfilesize();  if(nfilelength == -1)  {  system.err.println("file length is not known!");  }  else if(nfilelength == -2)  {  system.err.println("file is not access!");  }  else {  for(int i=0;i=400)  {  processerrorcode(responsecode);  return -2; //-2 represent access is error  }    string sheader;    for(int i=1;;i++)  {  //datainputstream in = new datainputstream(httpconnection.getinputstream ());  //utility.log(in.readline());  sheader=httpconnection.getheaderfieldkey(i);  if(sheader!=null)  {  if(sheader.equals("content-length"))  {  nfilelength = integer.parseint(httpconnection.getheaderfield(sheader));  break;  }  }  else break;  }  }  catch(ioexception e){e.printstacktrace ();}  catch(exception e){e.printstacktrace ();}    utility.log(nfilelength);    return nfilelength;  }    //保存下载信息(文件指针位置)  private void write_npos()  {  try{  output = new dataoutputstream(new fileoutputstream(tmpfile));  output.writeint(nstartpos.length);  for(int i=0;i 0 && nstartpos < nendpos && !bstop)  {  nstartpos += fileaccessi.write(b,0,nread);  //if(nthreadid == 1)  // utility.log("nstartpos = " + nstartpos + ", nendpos = " + nendpos);  }    utility.log("thread " + nthreadid + " is over!");  bdownover = true;  //npos = fileaccessi.write (b,0,nread);  }  catch(exception e){e.printstacktrace ();}  }  }    //打印回应的头信息  public void logresponsehead(httpurlconnection con)  {  for(int i=1;;i++)  {  string header=con.getheaderfieldkey(i);  if(header!=null)  //responseheaders.put(header,httpconnection.getheaderfield(header));  utility.log(header+" : "+con.getheaderfield(header));  else break;  }  }    public void splitterstop()  {  bstop = true;  }   }    /* **fileaccess.java */ package netfox;  import java.io.*;    public class fileaccessi implements serializable{    randomaccessfile osavedfile;  long npos;    public fileaccessi() throws ioexception  {  this("",0);  }    public fileaccessi(string sname,long npos) throws ioexception  {  osavedfile = new randomaccessfile(sname,"rw");  this.npos = npos;  osavedfile.seek(npos);  }    public synchronized int write(byte[] b,int nstart,int nlen)  {  int n = -1;  try{  osavedfile.write(b,nstart,nlen);  n = nlen;  }  catch(ioexception e)  {  e.printstacktrace ();  }    return n;  }   }    /* **siteinfobean.java */ package netfox;    public class siteinfobean {    private string ssiteurl; //sites url  private string sfilepath; //saved files path  private string sfilename; //saved files name  private int nsplitter; //count of splited downloading file    public siteinfobean()  {  //default value of nsplitter is 5  this("","","",5);  }    public siteinfobean(string surl,string spath,string sname,int nspiltter)  {  ssiteurl= surl;  sfilepath = spath;  sfilename = sname;  this.nsplitter = nspiltter;   }    public string getssiteurl()  {  return ssiteurl;  }    public void setssiteurl(string value)  {  ssiteurl = value;  }    public string getsfilepath()  {  return sfilepath;  }    public void setsfilepath(string value)  {  sfilepath = value;  }    public string getsfilename()  {  return sfilename;  }    public void setsfilename(string value)  {  sfilename = value;  }    public int getnsplitter()  {  return nsplitter;  }   public void setnsplitter(int ncount)  {  nsplitter = ncount;  }  }    /* **utility.java */ package netfox;    public class utility {    public utility()  {  }    public static void sleep(int nsecond)  {  try{  thread.sleep(nsecond);  }  catch(exception e)  {  e.printstacktrace ();  }  }    public static void log(string smsg)  {  system.err.println(smsg);  }    public static void log(int smsg)  {  system.err.println(smsg);  }  }    /* **testmethod.java */ package netfox;    public class testmethod {    public testmethod()  { ///xx/weblogic60b2_win.exe  try{  siteinfobean bean = new siteinfobean("http://localhost/xx/weblogic60b2_win.exe","l:\\temp","weblogic60b2_win.exe",5);  //siteinfobean bean = new siteinfobean("http://localhost:8080/down.zip","l:\\temp","weblogic60b2_win.exe",5);  sitefilefetch filefetch = new sitefilefetch(bean);  filefetch.start();  }  catch(exception e){e.printstacktrace ();}   }    public static void main(string[] args)  {  new testmethod();  }  }  

以上就是对Android 断点续传的资料整理,后续继续补充相关资料,谢谢大家对本站的支持!

更多相关文章

  1. Android(安卓)避免主线程执行网络请求之Activity/Fragment 结束
  2. Android(安卓)编译环境小语种丢失Bug
  3. Android中的Service 与 Thread 的区别
  4. Android(安卓)SDK目录及版本号区别
  5. Android系统文件夹结构解析
  6. android游戏编程的学习笔记(以植物大战僵尸等游戏源代码解析为例)
  7. Android(安卓)ListView的每个子Item如何设置高度
  8. Android(安卓)中常用ADB命令介绍
  9. Android系统上实现应用程序的静默安装

随机推荐

  1. android Animation 动画效果介绍 续 .
  2. android EditText inputType 及 android:
  3. Android的建议
  4. Android(安卓)内核剖析
  5. 《Android编程入门很简单》PDF版电子书下
  6. android EditText inputType 及 android:
  7. shape的使用总结
  8. Android(安卓)GWES之Android消息系统
  9. 如何跟踪调试Android的源码
  10. android编译过程详解(一)