亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關于我們
? 蟲蟲下載站

?? uploaddownload.txt

?? java實現斷點續傳多線程下載 java實現斷點續傳多線程下載
?? TXT
字號:
(一)斷點續傳的原理 
其實斷點續傳的原理很簡單,就是在Http的請求上和一般的下載有所不同而已。
打個比方,瀏覽器請求服務器上的一個文時,所發出的請求如下:
假設服務器域名為wwww.sjtu.edu.cn,文件名為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實現斷點續傳的關鍵幾點 


(1)用什么方法實現提交RANGE: bytes=2000070-。
當然用最原始的Socket是肯定能完成的,不過那樣太費事了,其實Java的net包中提供了這種功能。代碼如下:
URL url = new URL("http://www.sjtu.edu.cn/down.zip");
HttpURLConnection httpConnection = 
(HttpURLConnection)url.openConnection


();
file://設置User-Agent
httpConnection.setRequestProperty("User-Agent","NetFox");
file://設置斷點續傳的開始位置
httpConnection.setRequestProperty("RANGE","bytes=2000070");
file://獲得輸入流
InputStream input = httpConnection.getInputStream();


從輸入流中取出的字節流就是down.zip文件從2000070開始的字節流。
大家看,其實斷點續傳用Java實現起來還是很簡單的吧。
接下來要做的事就是怎么保存獲得的流到文件中去了。


保存文件采用的方法。
我采用的是IO包中的RandAccessFile類。
操作相當簡單,假設從2000070處開始保存文件,代碼如下:
RandomAccess oSavedFile = new 
RandomAccessFile("down.zip","rw");
long nPos = 2000070;
file://定位文件指針到nPos位置
oSavedFile.seek(nPos);
byte[] b = new byte[1024];
int nRead;
file://從輸入流中讀入字節流,然后寫到文件中
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測試類。


下面是源程序: 
/*
**SiteFileFetch.java
*/
package NetFox;
import java.io.*;
import java.net.*;


public class SiteFileFetch extends Thread {


SiteInfoBean siteInfoBean = null; file://文件信息Bean
long[] nStartPos; file://開始位置
long[] nEndPos; file://結束位置
FileSplitterFetch[] fileSplitterFetch; file://子線程對象
long nFileLength; file://文件長度
boolean bFirst = true; file://是否第一次取文件
boolean bStop = false; file://停止標志
File tmpFile; file://文件下載的臨時信息
DataOutputStream output; file://輸出到文件的輸出流


public SiteFileFetch(SiteInfoBean bean) throws IOException
{
siteInfoBean = bean;
file://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()
{
file://獲得文件長度
file://分割文件
file://實例FileSplitterFetch
file://啟動FileSplitterFetch線程
file://等待子線程返回
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;
}
}


file://啟動子線程
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();


file://等待子線程結束
file://int count = 0;
file://是否結束while循環
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;


file://count++;
file://if(count>4)
// siteStop();
}


System.err.println("文件下載結束!");
}
catch(Exception e){e.printStackTrace ();}
}


file://獲得文件長度
public long getFileSize()
{
int nFileLength = -1;
try{
URL url = new URL(siteInfoBean.getSSiteURL());
HttpURLConnection httpConnection = 
(HttpURLConnection)url.openConnection ();
httpConnection.setRequestProperty("User-Agent","NetFox");


int responseCode=httpConnection.getResponseCode();
if(responseCode>=400)
{
processErrorCode(responseCode);
return -2; file://-2 represent access is error
}


String sHeader;


for(int i=1;;i++)
{
file://DataInputStream in = new 
DataInputStream(httpConnection.getInputStream ());
file://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;
}


file://保存下載信息(文件指針位置)
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 ();}
}


file://讀取保存的下載信息(文件指針位置)
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 processErrorCode(int nErrorCode)
{
System.err.println("Error Code : " + nErrorCode);
}


file://停止文件下載
public void siteStop()
{
bStop = true;
for(int i=0;ifileSplitterFetch[i].splitterStop();


}
}
/*
**FileSplitterFetch.java
*/
package NetFox;


import java.io.*;
import java.net.*;


public class FileSplitterFetch extends Thread {


String sURL; file://File URL
long nStartPos; file://File Snippet Start Position
long nEndPos; file://File Snippet End Position
int nThreadID; file://Thread's ID
boolean bDownOver = false; file://Downing is over
boolean bStop = false; file://Stop identical
FileAccessI fileAccessI = null; file://File Access interface


public 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 < nEndPos && !bStop)
{


try{
URL url = new URL(sURL);
HttpURLConnection httpConnection = 
(HttpURLConnection)url.openConnection ();
httpConnection.setRequestProperty("User-Agent","NetFox");
String sProperty = "bytes="+nStartPos+"-";
httpConnection.setRequestProperty("RANGE",sProperty);
Utility.log(sProperty);


InputStream input = httpConnection.getInputStream();
file://logResponseHead(httpConnection);


byte[] b = new byte[1024];
int nRead;
while((nRead=input.read(b,0,1024)) > 0 && nStartPos < nEndPos 
&& !bStop)
{
nStartPos += fileAccessI.write(b,0,nRead);
file://if(nThreadID == 1)
// Utility.log("nStartPos = " + nStartPos + ", nEndPos = " + 
nEndPos);
}


Utility.log("Thread " + nThreadID + " is over!");
bDownOver = true;
file://nPos = fileAccessI.write (b,0,nRead);
}
catch(Exception e){e.printStackTrace ();}
}
}


file://打印回應的頭信息
public void logResponseHead(HttpURLConnection con)
{
for(int i=1;;i++)
{
String header=con.getHeaderFieldKey(i);
if(header!=null)
file://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; file://Site's URL
private String sFilePath; file://Saved File's Path
private String sFileName; file://Saved File's Name
private int nSplitter; file://Count of Splited Downloading File


public SiteInfoBean()
{
file://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);
file://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();
}
}  
 
 
    發表時間:2005-07-06 13:57  
 

?? 快捷鍵說明

復制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
久久久久久久av麻豆果冻| 久久精品久久精品| 蜜桃av一区二区三区电影| 成人自拍视频在线| 欧美一区二区成人6969| 17c精品麻豆一区二区免费| 麻豆精品新av中文字幕| 在线观看欧美黄色| 国产精品传媒视频| 国产美女视频一区| 91麻豆精品91久久久久同性| 亚洲欧美一区二区视频| 国产在线不卡一区| 日韩三级在线免费观看| 亚洲一区二区欧美| 大陆成人av片| 久久嫩草精品久久久精品| 日韩和的一区二区| 日本久久一区二区三区| 国产精品网站在线| 国产尤物一区二区| 久久综合999| 狠狠色丁香婷婷综合| 日韩一级精品视频在线观看| 亚洲妇女屁股眼交7| 欧美三级午夜理伦三级中视频| 日韩伦理电影网| 99精品在线免费| 亚洲免费在线视频| 日本道在线观看一区二区| 亚洲精品久久7777| 91国内精品野花午夜精品| 亚洲视频一二三| 日本道免费精品一区二区三区| 亚洲精品一二三| 日本韩国精品在线| 午夜在线成人av| 7777精品久久久大香线蕉| 亚洲v中文字幕| 91精品国产福利| 国内精品写真在线观看| 精品国内片67194| 国产一区二区三区在线观看免费 | 欧美精品xxxxbbbb| 午夜欧美大尺度福利影院在线看| 欧美日韩国产另类一区| 奇米影视7777精品一区二区| 日韩精品中文字幕一区| 国产激情偷乱视频一区二区三区| 久久精品欧美一区二区三区麻豆| 成人一区二区三区| 综合在线观看色| 欧美日韩一区二区三区高清| 美女视频黄久久| 久久久久久久久久久久久夜| 成人av一区二区三区| 亚洲一级二级在线| 91精品国产综合久久香蕉麻豆| 波多野结衣亚洲| 自拍偷拍欧美激情| 3d动漫精品啪啪一区二区竹菊 | 亚洲永久精品大片| 经典三级在线一区| 五月婷婷久久丁香| 欧美一区二区三区免费视频| 国产麻豆成人传媒免费观看| 中文字幕欧美一| 在线播放91灌醉迷j高跟美女 | 国产欧美精品国产国产专区| 91国偷自产一区二区开放时间 | 欧美日韩高清在线| 豆国产96在线|亚洲| 香蕉乱码成人久久天堂爱免费| 久久综合久久综合亚洲| 91日韩精品一区| 免费成人美女在线观看| 国产精品免费免费| 欧美一区二区在线不卡| 99久久国产综合精品女不卡| 日韩av二区在线播放| 中文字幕一区二区三区在线观看| 欧美精品高清视频| 99r精品视频| 国产成人aaaa| 国内久久婷婷综合| 丝袜亚洲精品中文字幕一区| 亚洲欧洲色图综合| 2021中文字幕一区亚洲| 欧美日韩视频在线一区二区| 成人精品一区二区三区四区 | 国产欧美一区二区三区鸳鸯浴 | 蜜臀久久久久久久| 亚洲已满18点击进入久久| 国产精品免费免费| 久久久久久久久久久久久夜| 日韩欧美专区在线| 777亚洲妇女| 欧美色网站导航| 91在线免费播放| 波多野结衣的一区二区三区| 国产91色综合久久免费分享| 久久不见久久见免费视频1| 亚洲成人精品影院| 亚洲影院久久精品| 亚洲自拍偷拍网站| 夜夜揉揉日日人人青青一国产精品| 欧美激情资源网| 国产三级一区二区三区| 精品国产欧美一区二区| 欧美一区二区日韩| 91精品国产综合久久久蜜臀图片 | 色婷婷久久一区二区三区麻豆| 成人av网站免费观看| 国产成人午夜高潮毛片| 国产精品99久久久久| 国产成人精品免费在线| 国产成人鲁色资源国产91色综| 久久99久久久久| 久久99九九99精品| 精品一区二区三区免费视频| 麻豆视频观看网址久久| 国内不卡的二区三区中文字幕| 日韩国产一区二| 极品少妇xxxx精品少妇| 国产在线精品一区二区| 不卡视频免费播放| 色偷偷一区二区三区| 欧美精品自拍偷拍| 日韩视频在线观看一区二区| 久久久综合网站| 亚洲美女淫视频| 日韩精品一级二级 | 91在线看国产| 欧美影院一区二区| 日韩视频中午一区| 中文字幕精品一区二区精品绿巨人| 18涩涩午夜精品.www| 亚洲国产欧美一区二区三区丁香婷| 天天色 色综合| 国产一区二区女| 色综合久久综合网97色综合| 欧美肥妇free| 国产精品免费看片| 肉肉av福利一精品导航| 国产aⅴ综合色| 在线观看不卡一区| 久久新电视剧免费观看| 国产精品人妖ts系列视频| 亚洲一区在线观看免费| 免费成人av在线| 91偷拍与自偷拍精品| 欧美一区二区高清| 亚洲青青青在线视频| 麻豆国产欧美日韩综合精品二区| 成人午夜激情影院| 6080国产精品一区二区| 中文字幕高清一区| 日本在线不卡一区| av电影在线观看一区| 日韩一区二区在线观看视频播放| 国产精品欧美极品| 蜜臀精品久久久久久蜜臀| 91久久精品国产91性色tv| 26uuu欧美日本| 亚洲动漫第一页| 不卡一区中文字幕| 在线91免费看| 亚洲永久精品国产| caoporm超碰国产精品| 日韩欧美国产精品一区| 亚洲精品成人精品456| 国产精品99精品久久免费| 在线电影欧美成精品| 亚洲综合色丁香婷婷六月图片| 国产a视频精品免费观看| 精品盗摄一区二区三区| 天堂成人国产精品一区| 91美女在线视频| 国产欧美日韩不卡| 久久精品99久久久| 日韩一区二区三区三四区视频在线观看 | 欧美在线观看一二区| 国产亚洲成aⅴ人片在线观看| 一区二区三区加勒比av| 91影视在线播放| 《视频一区视频二区| 成人18视频日本| 国产欧美中文在线| 国产精品一区专区| 精品少妇一区二区三区在线播放 | 久久综合五月天婷婷伊人| 日本免费在线视频不卡一不卡二| 91国产视频在线观看| 亚洲免费在线电影| 色偷偷88欧美精品久久久| 中文字幕亚洲欧美在线不卡| 成人激情综合网站| 中文字幕中文在线不卡住| 成人久久久精品乱码一区二区三区| 久久精品亚洲精品国产欧美kt∨|