(1) The principle of breakpoint resumes is that the principles of the breakpoint are very simple, that is, in HTTP's request and general downloads. When you make a bit, the request is as follows: assuming that the server domain is www.sjtu.edu.cn, the file name is Down.zip. Get /down.zip http / 1.1accept: image / gif, image / x-xbitmap, image / jpeg, image / pjpeg, application / vnd.ms-excel, application / msword, Application / VND.MS-PowerPoint, * / * Accept-language: zh-cnaccept-encoding: Gzip, deflateUser-agent: mozilla / 4.0 (compatible; msie 5.01; windows nt 5.0) Connection: Keep-Alive
After receiving the request, the server is required to find the requested file, extract the file information, and then return to the browser, return information 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 continues to continue downloading from the place where the file has been downloaded. So add more information when the client browser is passed to the web server - where to start. Below is a "browser" compiled by yourself to pass the request information to the web server, requiring starting from 200,00070 bytes. Get /down.zip http / 1.0User-agent: Netfoxrange: Bytes = 2000070-Accept: Text / HTML, Image / GIF, Image / JPEG, *; Q = .2, * / *; q=.2
Take a closer look, you will find more than a row: bytes = 2000070 - The meaning of this is to tell the server down.zip This file starts from 200,000 bytes, and the previous byte is not available. After receiving this request, the return information is as follows: 206Content-length = 106786028content-range = bytes 2000070-106786027 / 106786028Date = mon, 30 apr 2001 12:55:20 gmtetag = W / "02ca57e173c11: 95b" content-type = Application / OCTET-Streamserver = Microsoft-IIS / 5.0last-Modified = Mon, 30 APR 2001 12:55:20 GMT
Comparison with the information returned by the previous server, it will find a line: Content-Range = bytes 2000070-106786027 / 106786028 The return code is also changed to 206, and no longer 200.
If you know the above principles, you can make a programming of the breakpoint.
(2) Java renewed key points
(1) What method is used to implement the submission: BYTES = 2000070-. Of course, the most primitive socket is certain, but it is too much, in fact, this function is provided in the Java NET package. Code is as follows: URL url = new URL ( "http://www.sjtu.edu.cn/down.zip"); HttpURLConnection httpConnection = (HttpURLConnection) url.openConnection (); // Set User-AgenthttpConnection.setRequestProperty ( " User-agent "," Netfox "); // Set the start position of the breakpoint HTTPConnection.seueStProperty (" Range "," BYTES = 2000070 "); // Get input stream inputStream Input = httpConnection.getinputStream (); The byte stream taken in the input stream is the byte stream from the Down.zip file from 2000070. Let's see that it is still very simple to achieve Java. The next thing to do is how to save the resulting stream to the file. The method of saving the file. I use the RandaccessFile class in the IO package. The operation is quite simple, assuming that the file is saved from 2000070, the code is as follows: randomaccess osavedfile = new randomaccessfile ("Down.zip", "RW"); long npos = 2000070; // Location file pointer to NPOS location OsavedFile.seek (NPOS ); byte [] b = new byte [1024]; int nread; // read the byte stream from the input stream, then Write While in the file ((NREAD = INPUT.READ (B, 0, 1024))> 0) {OSAVEDFILE.WRITE (B, 0, NREAD);}, it is also very simple. The next thing to do is to integrate into a complete program. Includes a series of thread control, and the like.
(3) The implementation of the breakpoint renewal kernel has maintained 6 classes, including a test class. SiteFileFetch.java is responsible for the capture of the entire file, controlling internal threads (FILESPLITTERFETCH). FILESPLITTERFETCH.JAVA is responsible for the capture of some files. FileAccess.java is responsible for the storage of documents. SiteInfoBean.java to grab the information, such as the directory, name, and the URL of the file, and the URL of the file. Utility.java tool class, put some simple way. TestMethod.java test class.
Below is the source program:
/ *
** SitefileFetch.java
* /
Package Netfox;
Import java.io. *;
Import java.net. *;
Public class sitefilefetch extends thread {
SiteInfobean SiteInfobean = null; // File Information Bean
Long [] nStartPos; // Start location
Long [] nendpos; // end position
FILESPLITTERFETCH [] FILESPLITTERFETCH; / / Sub-threaded object
Long nfilelength; // file length
Boolean bfirst = true; // Whether to take a document for the first time
Boolean bstop = false; // stop sign
File TmpFile; // Temporary information downloaded
DataOutputStream Output; // Output to File 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 ()
{
// Get the file length
// Split file
// Example FileSplitterFetch
// Start FileSplitterFetch thread
// Waiting for the sub-thread to return
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 { NStartPOS [I] = (long) (i * (nfilelength / nstartpos.length); } For (int i = 0; I { Nendpos [i] = nStartPOS [i 1]; } Nendpos [NendPos.length-1] = NFileLength; } } // Introduction FileSplitterFetch = new filesplitterfetch [nstartpos.length]; For (int i = 0; i { FILESPLITTERFETCH [I] = new filesplitterFetch (SiteInfobean.getssiteURL (), SiteInfobean.getsfilepath () file.separator siteInfobean.getsFileName (), NStartPOS [I], NendPos [i], i); Utility.log ("Thread" i ", NStartPOS =" NStartPOS [i] ", Nendpos =" NendPos [i]); FileSplitterFetch [i] .start (); } // filesplitterfetch [npos.length-1] = new filesplitterfetch (siteInfobean.getssiteURL (), SiteInfobean.getsFilePath () file.separator siteInfobean.getsfileName (), npos [npos.length-1], nfilelength, npos.length-1); // utility.log ("thread" (NPos.LEngth-1 ) ", nStartPOS =" NPOS [NPOS.LENGTH-1] ", Nendpos = " nfilelength); // filesplitterfetch [npos.length-1] .Start (); // Waiting for the end of the sub-thread // INT count = 0; / / End WHILE loop Boolean Breakwhile = false; While (! BSTOP) { Write_npos (); Utility.sleep (500); Breakwhile = true; For (int i = 0; i { IF (! filesplitterfetch [i] .bdownover) { Breakwhile = false; Break; } } IF (BreakWhile) Break; // COUNT ; // if (count> 4) // SiteStop (); } System.err.println ("File Downloads!"); } Catch (Exception E) {E.PrintStackTrace (); } // Get the file length Public long getFilesize () { INT nfileLength = -1; Try { URL URL = New URL (SiteInfoBean.getssiteURL ()); HTTPURLCONNECTION httpConnection = (httpurlconnection) URL.OpenConnection (); HttpConnection.seueStProperty ("User-Agent", "Netfox"); Int responsecode = httpConnection.getResponsecode (); IF (Responsecode> = 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; } / / Save download information (file pointer position) Private void write_npos () { Try { Output = New DataOutputStream (New FileoutputStream (TMPFILE)); Output.writeint (NStartPos.Length); For (int i = 0; i { // output.writelong (NPOS [i]); Output.writelong (filesplitterfetch [i] .nstartpos); Output.writelong (filesplitterfetch [i] .nendpos); } Output.close (); } Catch (IOException E) {E.PrintStackTrace (); Catch (Exception E) {E.PrintStackTrace (); } // Read save download information (file pointer position) Private void read_npos () { Try { DataInputStream Input = New DataInputStream (New FileInputStream (TMPFILE)); INT ncount = INPUT.READINT (); NStartPOS = New long [ncount]; Nendpos = new long [ncount]; For (int i = 0; i { NSTARTPOS [I] = INPUT.READLONG (); Nendpos [I] = INPUT.READLONG (); } INPUT.CLOSE (); } Catch (IOException E) {E.PrintStackTrace (); Catch (Exception E) {E.PrintStackTrace (); } Private Void ProcesserRrorcode (int NerrorCode) { System.err.Println ("Error Code:" NerrorCode); } // Stop file download Public void sitestop () { BSTOP = TRUE; For (int i = 0; i FILESPLITTERFETCH [I] .splitterstop (); } } / * ** FileSplitterFetch.java * / Package Netfox; Import java.io. *; Import java.net. *; Public class filesplitterfetch eXtends thread { String surl; // file URL Long nStartPos; // file snippet start position Long Nendpos; // File Snippet End Position INT NTHREADID; // Thread's ID Boolean bdownover = false; // downing is over Boolean bstop = false; // stop identical FileAccessi FileAccessi = NULL; // File Access InterfacePublic FileSplitterFetch (String SURL, String Sname, Long Nstart, Long Nend, Int ID) THROWS IOException { THIS.SURL = SURL; THIS.NSTARTPOS = NSTART; THIS.NENDPOS = NEND; nthreadid = ID; FileAccessi = New FileAccessi (SNAME, NSTARTPOS); } Public void Run () { While (NStartPOS { Try { URL URL = New URL (SURL); HTTPURLCONNECTION httpConnection = (httpurlconnection) URL.OpenConnection (); HttpConnection.seueStProperty ("User-Agent", "Netfox"); String Sproperty = "Bytes =" NStartPOS "-" HttpConnection.SetRequestProperty ("Range", Sproperty); Utility.log (Sproperty); InputStream INPUT = httpConnection.getinputStream (); // logResponsehead (httpConnection); Byte [] b = new byte [1024]; Int nread; While (NREAD = INPUT.READ (B, 0, 1024))> 0 && NStartPOS { 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 (); } } // Print the header information 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 imports serializable { Randomaccessfile OsavedFile; Long NPOS; Public FileAccessi () THROWS IOEXCEPTION { THIS ("", 0); } Public FileAccessi (String Sname, long npos) throws oException { 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; // site's url Private string sfilepath; // Saved File's Path Private string sfilename; // Saved File's 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 (); } }