What this article is about is the content of Android breakpoint continuation, which is introduced in detail in the form of an example.
1. The principle of breakpoint continuous transmission
In fact, the principle of breakpoint continuation is very simple, which is that it is different from general downloads on http requests.
For example, when the browser requests a text on the server, the request is as follows:
Suppose the server domain name is /android and the file name is.
get / http/1.1
accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/-
excel, application/msword, application/-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
After the server receives the request, it searches for the requested file as required, extracts the file information, and then returns it to the browser. The return information is as follows:
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
The so-called breakpoint continuous transmission means that you need to continue downloading from the place where the file has been downloaded. So when the client browser passes it to the web server, you need to add an extra message - where to start.
The following is a "browser" I compiled by myself to pass the request information to the web server, requiring it to start from 2000070 bytes.
get / http/1.0
user-agent: netfox
range: bytes=2000070-
accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
If you look closely, you will find that there is an extra line range: bytes=2000070-
This line means telling the server that the file starts to be transmitted from 2000070 bytes, and the previous bytes are no longer required.
After the server receives this request, the information returned is as follows:
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
Compare with the information returned by the previous server and you will find that a line is added:
content-range=bytes 2000070-106786027/106786028
The returned code has also been changed to 206, not 200 anymore.
Once you understand the above principles, you can program breakpoint continuous transmission.
2. Some key points in Java to implement breakpoint continuous transmission
What method should be used to implement the commit range: bytes=2000070-?
Of course, it can be done with the most original socket, but that's too much trouble. In fact, this function is provided in the java net package. The code is as follows:
Java code
url url = new url("/android/"); httpurlconnection httpconnection = (httpurlconnection)(); //Set user-agent("user-agent","netfox"); //Set the start position of the breakpoint continuous transmission("range","bytes=2000070"); //Get input streaminputstream input = (); The byte stream taken from the input stream is the file2000070The beginning of the byte stream。 Everyone see,In fact, breakpoints continue to be transmittedjavaIt's still very simple to implement。 The next thing to do is how to save the obtained stream into the file。 Methods of saving files:I'm usingioIn the packagerandaccessfilekind。 Very easy to operate,Assume from2000070Start saving files,The code is as follows: JavaCode randomaccess osavedfile = new randomaccessfile("","rw"); long npos = 2000070; //Locate the file pointer to npos location(npos); byte[] b = new byte[1024]; int nread; //Read the byte stream from the input stream and write it to the filewhile((nread=(b,0,1024)) > 0) { (b,0,nread); } How about it,It's very simple, too。 The next thing to do is to integrate it into a complete program。Including a series of thread controls, etc.。 three、Implementation of breakpoint continuous transmission kernel Mainly used6个kind,包括一个测试kind。 Responsible for the capture of the entire file,Control internal threads(filesplitterfetchkind)。 Responsible for crawling some files。 Responsible for the storage of files。 Information about the file to be crawled,Directory of file saved,name,Crawling filesurlwait。 工具kind,Put some simple methods。 测试kind。 Four、Instance source code Below is the source program: JavaCode /* ** */ package netfox; import .*; import .*; public class sitefilefetch extends thread { siteinfobean siteinfobean = null; //File information beanlong[] nstartpos; //Start positionlong[] nendpos; //End Locationfilesplitterfetch[] filesplitterfetch; //Child thread objectlong nfilelength; //File lengthboolean bfirst = true; //Is the first time the file is retrievedboolean bstop = false; //Stop signfile tmpfile; //Temporary information on file downloaddataoutputstream output; //Output stream to file public sitefilefetch(siteinfobean bean) throws ioexception { siteinfobean = bean; //tmpfile = ("zhong","1111",new file(())); tmpfile = new file(()+ + ()+".info"); if( ()) { bfirst = false; read_npos(); } else { nstartpos = new long[()]; nendpos = new long[()]; } } public void run() { //Get file length//Split the file//Instance filesplitterfetch//Start the filesplitterfetch thread//Waiting for the child thread to returntry{ if(bfirst) { nfilelength = getfilesize(); if(nfilelength == -1) { ("file length is not known!"); } else if(nfilelength == -2) { ("file is not access!"); } else { for(int i=0;i<;i++) { nstartpos = (long)(i*(nfilelength/)); } for(int i=0;i<-1;i++) { nendpos = nstartpos[i+1]; } nendpos[-1] = nfilelength; } } //Starting child threadfilesplitterfetch = new filesplitterfetch[]; for(int i=0;i<;i++) { filesplitterfetch = new filesplitterfetch((), () + + (), nstartpos,nendpos,i); ("thread " + i + " , nstartpos = " + nstartpos + ", nendpos = " + nendpos); (); } // filesplitterfetch[-1] = new filesplitterfetch((), () + + (),npos[-1],nfilelength,-1); // ("thread " + (-1) + " , nstartpos = " + npos[-1] + ", nendpos = " + nfilelength); // filesplitterfetch[-1].start(); //Waiting for the child thread to end//int count = 0; //Whether loop endsboolean breakwhile = false; while(!bstop) { write_npos(); (500); breakwhile = true; for(int i=0;i<;i++) { if(!) { breakwhile = false; break; } } if(breakwhile) break; //count++; //if(count>4) // sitestop(); } ("File download ends!"); } catch(exception e){ ();} } //Get file lengthpublic long getfilesize() { int nfilelength = -1; try{ url url = new url(()); httpurlconnection httpconnection = (httpurlconnection) (); ("user-agent","netfox"); int responsecode=(); if(responsecode>=400) { processerrorcode(responsecode); return -2; //-2 represent access is error } string sheader; for(int i=1;;i++) { //datainputstream in = new datainputstream( ()); //(()); sheader=(i); if(sheader!=null) { if(("content-length")) { nfilelength = ((sheader)); break; } } else break; } } catch(ioexception e){ ();} catch(exception e){ ();} (nfilelength); return nfilelength; } //Save download information (file pointer location)private void write_npos() { try{ output = new dataoutputstream(new fileoutputstream(tmpfile)); (); for(int i=0;i<;i++) { // (npos); (); (); } (); } catch(ioexception e){ ();} catch(exception e){ ();} } //Read the saved download information (file pointer location)private void read_npos() { try{ datainputstream input = new datainputstream(new fileinputstream(tmpfile)); int ncount = (); nstartpos = new long[ncount]; nendpos = new long[ncount]; for(int i=0;i<;i++) { nstartpos = (); nendpos = (); } (); } catch(ioexception e){ ();} catch(exception e){ ();} } private void processerrorcode(int nerrorcode) { ("error code : " + nerrorcode); } //Stop file downloadpublic void sitestop() { bstop = true; for(int i=0;i<;i++) (); } } /* ** */ package netfox; import .*; import .*; public class filesplitterfetch extends thread { string surl; //file url long nstartpos; //file snippet start position long nendpos; //file snippet end position int nthreadid; //threads id boolean bdownover = false; //downing is over boolean bstop = false; //stop identical fileaccessi fileaccessi = null; //file access interface public filesplitterfetch(string surl,string sname,long nstart,long nend,int id) throws ioexception { = surl; = nstart; = nend; nthreadid = id; fileaccessi = new fileaccessi(sname,nstartpos); } public void run() { while(nstartpos < nendpos && !bstop) { try{ url url = new url(surl); httpurlconnection httpconnection = (httpurlconnection) (); ("user-agent","netfox"); string sproperty = "bytes="+nstartpos+"-"; ("range",sproperty); (sproperty); inputstream input = (); //logresponsehead(httpconnection); byte[] b = new byte[1024]; int nread; while((nread=(b,0,1024)) > 0 && nstartpos < nendpos && !bstop) { nstartpos += (b,0,nread); //if(nthreadid == 1) // ("nstartpos = " + nstartpos + ", nendpos = " + nendpos); } ("thread " + nthreadid + " is over!"); bdownover = true; //npos = (b,0,nread); } catch(exception e){ ();} } } //Print the header of the responsepublic void logresponsehead(httpurlconnection con) { for(int i=1;;i++) { string header=(i); if(header!=null) //(header,(header)); (header+" : "+(header)); else break; } } public void splitterstop() { bstop = true; } } /* ** */ package netfox; import .*; 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"); = npos; (npos); } public synchronized int write(byte[] b,int nstart,int nlen) { int n = -1; try{ (b,nstart,nlen); n = nlen; } catch(ioexception e) { (); } return n; } } /* ** */ 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; = 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; } } /* ** */ package netfox; public class utility { public utility() { } public static void sleep(int nsecond) { try{ (nsecond); } catch(exception e) { (); } } public static void log(string smsg) { (smsg); } public static void log(int smsg) { (smsg); } } /* ** */ 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/","l:\\temp","weblogic60b2_win.exe",5); sitefilefetch filefetch = new sitefilefetch(bean); (); } catch(exception e){ ();} } public static void main(string[] args) { new testmethod(); } }
The above is a compilation of the information on Android breakpoint transmission. We will continue to add relevant information in the future. Thank you for your support for this site!