java斷點續(xù)傳_第1頁
java斷點續(xù)傳_第2頁
java斷點續(xù)傳_第3頁
已閱讀5頁,還剩6頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

1、Java 實現(xiàn)斷點續(xù)傳原理 參考代碼 注 :類用紅色字體表示 ,所需類已經(jīng)添加至壓縮包代碼局部 -類的字體 , Package 的字體 ,import 導(dǎo)包的字體中文注釋均高亮上色 ,每個類前都有類的注釋/*/ 格式一斷點續(xù)傳的原理 其實斷點續(xù)傳的原理 ,就是在的請求上和一般的下載有所不同而已。打個比方,瀏覽器請求效勞器上的一個文時,所發(fā)出的請求如下: 假設(shè)效勞器域名為 w ,文件名為 down.zip 。excel, application/msword, application/vnd.ms-powerpoint, */* Accept-Language: zh-cnAc

2、cept-Encoding: gzip, deflateUser-Agent: Mozilla/4.0 compatible; MSIE 5.01; Windows NT 5.0Connection: Keep-Alive效勞器收到請求后, 按要求尋找請求的文件, 提取文件的信息,然后返回給瀏覽器,返回信 息如下:200Content-Length=106786028 Accept-Ranges=bytesDate=Mon, 30 Apr 2001 12:56:11 GMT ETag=W/"02ca57e173c11:95b" Content-Type=applicatio

3、n/octet-streamLast-Modified=Mon, 30 Apr 2001 12:56:11 GMT所謂斷點續(xù)傳,也就是要從文件已經(jīng)下載的地方開始繼續(xù)下載。所以在客戶端瀏覽器傳給 Web 效勞器的時候要多加一條信息-從哪里開始。下面是用自己編的一個瀏覽器來傳遞請求信息給 Web效勞器,要求從2000070字節(jié)開始。User-Agent: NetFoxRANGE: bytes=2000070-Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2仔細看一下就會發(fā)現(xiàn)多了一行 RANGE: bytes=2000070-這

4、一行的意思就是告訴效勞器 down.zip 這個文件從 2000070 字節(jié)開始傳,前面的字節(jié)不用 傳了。效勞器收到這個請求以后,返回的信息如下:206Content-Length=106786028Content-Range=bytes 2000070-106786027/106786028Date=Mon, 30 Apr 2001 12:55:20 GMTETag=W/"02ca57e173c11:95b"Content-Type=application/octet-streamLast-Modified=Mon, 30 Apr 2001 12:55:20 GMT和前面

5、效勞器返回的信息比擬一下,就會發(fā)現(xiàn)增加了一行:Content-Range=bytes 2000070-106786027/106786028 返回的代碼也改為 206 了,而不再是 200 了。 知道了以上原理,就可以進行斷點續(xù)傳的編程了。(二 )Java 實現(xiàn)斷點續(xù)傳的關(guān)鍵幾點(1)用什么方法實現(xiàn)提交 RANGE: bytes=2000070- 。當然用最原始的Socket是肯定能完成的,不過那樣太費事了,其實Java的net包中提供了這種功能。代碼如下:URL url = new URL(" :/ /down.zip");();/設(shè)置 User-Age

6、ntConnection.setRequestProperty("User-Agent","NetFox");/設(shè)置斷點續(xù)傳的開始位置Connection.setRequestProperty("RANGE","bytes=2000070"); /獲得輸入流InputStream input = Connection.getInputStream();從輸入流中取出的字節(jié)流就是 down.zip 文件從 2000070 開始的字節(jié)流。 大家看,其實斷點續(xù)傳用 Java 實現(xiàn)起來還是很簡單的吧。 接下來要做的事就是怎

7、么保存獲得的流到文件中去了。保存文件采用的方法。我采用的是 IO 包中的 RandAccessFile 類。操作相當簡單,假設(shè)從 2000070 處開始保存文件,代碼如下:RandomAccess oSavedFile = new RandomAccessFile("down.zip","rw"); long nPos = 2000070;/定位文件指針到 nPos 位置oSavedFile.seek(nPos);byte b = new byte1024;int nRead;/從輸入流中讀入字節(jié)流,然后寫到文件中 while(nRead=input.r

8、ead(b,0,1024) > 0) oSavedFile.write(b,0,nRead);怎么樣,也很簡單吧。 接下來要做的就是整合成一個完整的程序了。包括一系列的線程控制等等。(三)斷點續(xù)傳內(nèi)核的實現(xiàn) 主要用了 6 個類,包括一個測試類。 負責(zé)整個文件的抓取,控制內(nèi)部線程 (FileSplitterFetch 類 )。 負責(zé)局部文件的抓取。負責(zé)文件的存儲。 要抓取的文件的信息,如文件保存的目錄,名字,抓取文件的 URL 等。 工具類,放一些簡單的方法。測試類。下面是參考源碼:(6個類我已經(jīng)單獨壓縮成文件,放在NetFoxpackage 下)效果圖如下:耳 NetFox.J | Fi

9、leAcce-ssl java7 Fi I eS p I itte rFetc h.J ava11 Sit eFile Fetch javaIJ | SitelnfoEean.javajj TestMethodJava| J Utility .java/*/package NetFox; import java.io.*;import java .n et.*;public class SiteFileFetch exte nds Thread SiteInfoBean siteInfoBean = null; 文件信息 Bean long n StartPos; 開始位置Ion g nEn

10、dPos; / 結(jié)束位置FileSplitterFetch fileSplitterFetch; / 子線程對象 long nFileLength; 文件長度 boolean bFirst = true; 是否第一次取文件 boolea n bStop = false; 停止標志 File tmpFile; 文件下載的臨時信息 DataOutputStream output; 輸出到文件的輸出流public SiteFileFetch(Site In foBea n bea n) throws IOExcepti onsite In foBea n = bea n;/tmpFile = Fil

11、e.createTempFile ("zhong","1111",new File(bean.getSFilePath();tmpFile = new File(bea n. getSFilePath()+File.separator + bea n. getSFileName()+".i nfo"); if(tmpFile.exists ()bFirst = false;read _n Pos();elsenStartPos = new longbean.getNSplitter(); nEndPos = new longbean.

12、getNSplitter(); public void run()/獲得文件長度/分割文件/實例 FileSplitterFetch/啟動 FileSplitterFetch 線程/等待子線程返回tryif(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!");elsef

13、or(int i=0;i<nStartPos.length;i+)nStartPosi = (long)(i*(nFileLength/nStartPos.length);for(int i=0;i<nEndPos.length-1;i+)nEndPosi = nStartPosi+1;nEndPosnEndPos.length-1 = nFileLength;/啟動子線程fileSplitterFetch = new FileSplitterFetchnStartPos.length;for(int i=0;i<nStartPos.length;i+)fileSplitte

14、rFetchi = new FileSplitterFetch(siteInfoBean.getSSiteURL(),siteInfoBean.getSFilePath() + File.separator + siteInfoBean.getSFileName(), nStartPosi,nEndPosi,i);Utility.log("Thread " + i + " , nStartPos = " + nStartPosi + ", nEndPos = " + nEndPosi); fileSplitterFetchi.star

15、t();/ fileSplitterFetchnPos.length-1 = new FileSplitterFetch(siteInfoBean.getSSiteURL(), siteInfoBean.getSFilePath() + File.separator + siteInfoBean.getSFileName(),nPosnPos.length-1,nFileLength,nPos.length-1);/ Utility.log("Thread " + (nPos.length-1) + " , nStartPos = " + nPosnPo

16、s.length-1 + ",nEndPos = " + nFileLength);/ fileSplitterFetchnPos.length-1.start();/等待子線程結(jié)束/int count = 0;/是否結(jié)束 while 循環(huán)boolean breakWhile = false;while(!bStop)write_nPos();Utility.sleep(500);breakWhile = true;for(int i=0;i<nStartPos.length;i+)if(!fileSplitterFetchi.bDownOver)breakWhile

17、 = false;break;if(breakWhile)break;/count+;/if(count>4)/ siteStop();System.err.println(" 文件下載結(jié)束! ");catch(Exception e)e.printStackTrace ();/獲得文件長度public long getFileSize()int nFileLength = -1;tryURL url = new URL(siteInfoBean.getSSiteURL();URLConnectionConnection = (URLConnection)url.op

18、enConnection ();Connection.setRequestProperty("User-Agent","NetFox");int responseCode= Connection.getResponseCode();if(responseCode>=400)processErrorCode(responseCode);return -2; /-2 represent access is errorString sHeader;for(int i=1;i+)/DataInputStream in = new DataInputStre

19、am(Connection.getInputStream ();/Utility.log(in.readLine();sHeader= Connection.getHeaderFieldKey(i); if(sHeader!=null) if(sHeader.equals("Content-Length")nFileLength = Integer.parseInt(Connection.getHeaderField(sHeader);break;elsebreak;catch(IOException e)e.printStackTrace (); catch(Except

20、ion e)e.printStackTrace ();Utility.log(nFileLength);return nFileLength;/保存下載信息文件指針位置private void write_nPos()tryoutput = new DataOutputStream(new FileOutputStream(tmpFile); output.writeInt(nStartPos.length);for(int i=0;i<nStartPos.length;i+)/ output.writeLong(nPosi); output.writeLong(fileSplitter

21、Fetchi.nStartPos); output.writeLong(fileSplitterFetchi.nEndPos);output.close();catch(IOException e)e.printStackTrace (); catch(Exception e)e.printStackTrace (); /讀取保存的下載信息文件指針位置 private void read_nPos()tryDataInputStream input = new DataInputStream(new FileInputStream(tmpFile); int nCount = input.re

22、adInt();nStartPos = new longnCount; nEndPos = new longnCount;for(int i=0;i<nStartPos.length;i+)nStartPosi = input.readLong(); nEndPosi = input.readLong();input.close();catch(IOException e)e.printStackTrace (); catch(Exception e)e.printStackTrace ();private void processErrorCode(int nErrorCode)Sys

23、tem.err.println("Error Code : " + nErrorCode);/停止文件下載public void siteStop()bStop = true;for(int i=0;i<nStartPos.length;i+) fileSplitterFetchi.splitterStop();/*/package NetFox;import java.io.*;import .*;public class FileSplitterFetch extends Thread String sURL; /File URLlong nStartPos; /

24、File Snippet Start Positionlong nEndPos; /File Snippet End Positionint nThreadID; /Thread's IDboolean bDownOver = false; /Downing is overboolean bStop = false; /Stop identicalFileAccessI fileAccessI = null; /File Access interfacethrowspublic FileSplitterFetch(String sURL,String sName,long nStart

25、,long nEnd,int id) IOExceptionthis.sURL = sURL;this.nStartPos = nStart;this.nEndPos = nEnd;nThreadID = id;fileAccessI = new FileAccessI(sName,nStartPos);public void run()while(nStartPos < nEndPos && !bStop) tryURL url = new URL(sURL);URLConnectionConnection = (URLConnection)url.openConnec

26、tion ();Connection.setRequestProperty("User-Agent","NetFox");String sProperty = "bytes="+nStartPos+"-" Connection.setRequestProperty("RANGE",sProperty);Utility.log(sProperty);InputStream input =Connection.getInputStream();/logResponseHead( Connection

27、);byte b = new byte1024;int nRead;while(nRead=input.read(b,0,1024) > 0 && nStartPos < nEndPos && !bStop)nStartPos += fileAccessI.write(b,0,nRead);/if(nThreadID = 1)/ Utility.log("nStartPos = " + nStartPos + ", nEndPos = " + nEndPos);Utility.log("Thread

28、" + nThreadID + " is over!");bDownOver = true;/nPos = fileAccessI.write (b,0,nRead);catch(Exception e)e.printStackTrace ();/打印回應(yīng)的頭信息public void logResponseHead(URLConnection con)for(int i=1;i+)String header=con.getHeaderFieldKey(i);if(header!=null)/responseHeaders.put(header, Connecti

29、on.getHeaderField(header);Utility.log(header+" : "+con.getHeaderField(header);elsebreak;public void splitterStop()bStop = true;/* FileAccessI.java( 類 )*/ package NetFox;import java.io.*;public class FileAccessI implements Serializable RandomAccessFile oSavedFile;long nPos;public FileAccess

30、I() 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;tryoSavedFile.write(b,nStart,n

31、Len);n = nLen; catch(IOException e)e.printStackTrace ();return n;/* */ 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 Download

32、ing 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 S

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論