java实现断点续传.docx

上传人:b****8 文档编号:9387624 上传时间:2023-05-18 格式:DOCX 页数:20 大小:21.48KB
下载 相关 举报
java实现断点续传.docx_第1页
第1页 / 共20页
java实现断点续传.docx_第2页
第2页 / 共20页
java实现断点续传.docx_第3页
第3页 / 共20页
java实现断点续传.docx_第4页
第4页 / 共20页
java实现断点续传.docx_第5页
第5页 / 共20页
java实现断点续传.docx_第6页
第6页 / 共20页
java实现断点续传.docx_第7页
第7页 / 共20页
java实现断点续传.docx_第8页
第8页 / 共20页
java实现断点续传.docx_第9页
第9页 / 共20页
java实现断点续传.docx_第10页
第10页 / 共20页
java实现断点续传.docx_第11页
第11页 / 共20页
java实现断点续传.docx_第12页
第12页 / 共20页
java实现断点续传.docx_第13页
第13页 / 共20页
java实现断点续传.docx_第14页
第14页 / 共20页
java实现断点续传.docx_第15页
第15页 / 共20页
java实现断点续传.docx_第16页
第16页 / 共20页
java实现断点续传.docx_第17页
第17页 / 共20页
java实现断点续传.docx_第18页
第18页 / 共20页
java实现断点续传.docx_第19页
第19页 / 共20页
java实现断点续传.docx_第20页
第20页 / 共20页
亲,该文档总共20页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

java实现断点续传.docx

《java实现断点续传.docx》由会员分享,可在线阅读,更多相关《java实现断点续传.docx(20页珍藏版)》请在冰点文库上搜索。

java实现断点续传.docx

java实现断点续传

java实现断点续传

(一)断点续传的原理

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

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

假设服务器域名为,文件名为down.zip。

GET/down.zipHTTP/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;MSIE5.01;WindowsNT5.0)

Connection:

Keep-Alive

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

200

Content-Length=106786028

Accept-Ranges=bytes

Date=Mon,30Apr200112:

56:

11GMT

ETag=W/"02ca57e173c11:

95b"

Content-Type=application/octet-stream

Server=Microsoft-IIS/5.0

Last-Modified=Mon,30Apr200112:

56:

11GMT

所谓断点续传,也就是要从文件已经下载的地方开始继续下载。

所以在客户端浏览器传给

Web服务器的时候要多加一条信息--从哪里开始。

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

GET/down.zipHTTP/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=bytes2000070-106786027/106786028

Date=Mon,30Apr200112:

55:

20GMT

ETag=W/"02ca57e173c11:

95b"

Content-Type=application/octet-stream

Server=Microsoft-IIS/5.0

Last-Modified=Mon,30Apr200112:

55:

20GMT

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

Content-Range=bytes2000070-106786027/106786028

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

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

(二)Java实现断点续传的关键几点

用什么方法实现提交RANGE:

bytes=2000070-。

当然用最原始的Socket是肯定能完成的,不过那样太费事了,其实Java的net包中提供了这种功能。

代码如下:

URLurl=newURL("

HttpURLConnectionhttpConnection=(HttpURLConnection)url.openConnection();

//设置User-Agent

httpConnection.setRequestProperty("User-Agent","NetFox");

//设置断点续传的开始位置

httpConnection.setRequestProperty("RANGE","bytes=2000070");

//获得输入流

InputStreaminput=httpConnection.getInputStream();

从输入流中取出的字节流就是down.zip文件从2000070开始的字节流。

大家看,其实断点续传用Java实现起来还是很简单的吧。

接下来要做的事就是怎么保存获得的流到文件中去了。

保存文件采用的方法。

我采用的是IO包中的RandAccessFile类。

操作相当简单,假设从2000070处开始保存文件,代码如下:

RandomAccessoSavedFile=newRandomAccessFile("down.zip","rw");

longnPos=2000070;

//定位文件指针到nPos位置

oSavedFile.seek(nPos);

byte[]b=newbyte[1024];

intnRead;

//从输入流中读入字节流,然后写到文件中

while((nRead=input.read(b,0,1024))>0){

oSavedFile.write(b,0,nRead);

}

怎么样,也很简单吧。

接下来要做的就是整合成一个完整的程序了。

包括一系列的线程控制等等。

(三)断点续传内核的实现

主要用了6个类,包括一个测试类。

1:

SiteFileFetch.Java-负责整个文件的抓取,控制内部线程(FileSplitterFetch)。

2:

FileSplitterFetch.Java-负责部分文件的抓取。

3:

FileAccess.Java-负责文件的存储。

4:

SiteInfoBean.Java-要抓取的文件的信息,如文件保存的目录,名字,抓取文件的URL等。

5:

Utility.Java-工具类,放一些简单的方法。

6:

TestMethod.Java-测试类。

首先创建继承Thread类的传输文件线程类,其JAVA文件名为SiteFileFetch.java,代码如下:

importjava.io.DataInputStream;

importjava.io.DataOutputStream;

importjava.io.File;

importjava.io.FileInputStream;

importjava.io.FileOutputStream;

importjava.io.IOException;

import.HttpURLConnection;

import.URL;

/**

*传输文件线程类。

*@authorzhang

*/

publicclassSiteFileFetchextendsThread{

SiteInfoBeansiteInfoBean=null;

/*文件位置指针*/

long[]nPos;

/*开始位置*/

long[]nStartPos;

/*结束位置*/

long[]nEndPos;

/*子线程对象*/

FileSplitterFetch[]fileSplitterFetch;

/*文件长度*/

longnFileLength;

/*是否第一次读取*/

booleanbFirst=true;

/*停止标志*/

booleanbStop=false;

/*文件传输临时信息*/

FiletmpFile;//

/*输出到文件的输出流*/

DataOutputStreamoutput;

publicSiteFileFetch(SiteInfoBeanbean)throwsIOException{

siteInfoBean=bean;

tmpFile=newFile(bean.getSFilePath()+File.separator+bean.getSFileName()+".info");

if(tmpFile.exists()){

bFirst=false;

read_nPos();

}else{

nStartPos=newlong[bean.getNSplitter()];

nEndPos=newlong[bean.getNSplitter()];

}

}

publicvoidrun(){

try{

if(bFirst){

//获得文件长度

nFileLength=getFileSize();

if(nFileLength==-1){

System.err.println("FileLengthisnotknown");

}elseif(nFileLength==-2){

System.err.println("Fileisnotaccess!

");

}else{

//分割下载文件

for(inti=0;i

nStartPos[i]=(long)(i*(nFileLength/nStartPos.length));

}

for(inti=0;i

nEndPos[i]=nStartPos[i+1];

}

nEndPos[nEndPos.length-1]=nFileLength;

}

}

//创建FileSplitterFetch类实例

fileSplitterFetch=newFileSplitterFetch[nStartPos.length];

//启动FileSplitterFetch线程

for(inti=0;i

fileSplitterFetch[i]=newFileSplitterFetch(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();

}

booleanbreakWhile=false;

//等待子线程结束

while(!

bStop){

write_nPos();

Utility.sleep(500);

breakWhile=true;

for(inti=0;i

//等待子线程返回

if(!

fileSplitterFetch[i].bDownOver){

breakWhile=false;

break;

}

}

//是否结束while循环

if(breakWhile)

break;

}

System.out.println("文件传输结束!

");

}catch(Exceptione){

e.printStackTrace();

}

}

/**

*获得文件长度

*@return

*/

publiclonggetFileSize(){

intnFileLength=-1;

try{

//创建与WEB服务器的连接

URLurl=newURL(siteInfoBean.getSSiteURL());

HttpURLConnectionhttpConnection=(HttpURLConnection)url.openConnection();

httpConnection.setRequestProperty("User-Agent","sample.resumebrokentransfer");

intresponseCode=httpConnection.getResponseCode();

if(responseCode>=400){

processErrorCode(responseCode);

//-2为WEB服务器响应错误

return-2;

}

StringsHeader;

for(inti=1;;i++){

sHeader=httpConnection.getHeaderFieldKey(i);

if(sHeader!

=null){

if(sHeader.equals("Content-Length")){

nFileLength=Integer.parseInt(httpConnection.getHeaderField(sHeader));

break;

}

}else{

break;

}

}

}catch(IOExceptione){

e.printStackTrace();

}catch(Exceptione){

e.printStackTrace();

}

Utility.log(nFileLength);

returnnFileLength;

}

/**

*保存传输文件指针位置

*/

privatevoidwrite_nPos(){

try{

output=newDataOutputStream(newFileOutputStream(tmpFile));

output.writeInt(nStartPos.length);

for(inti=0;i

output.writeLong(fileSplitterFetch[i].nStartPos);

output.writeLong(fileSplitterFetch[i].nEndPos);

}

output.close();

}catch(IOExceptione){

e.printStackTrace();

}catch(Exceptione){

e.printStackTrace();

}

}

/**

*读取保存的下载文件指针位置

*/

privatevoidread_nPos(){

try{

DataInputStreaminput=newDataInputStream(newFileInputStream(tmpFile));

intnCount=input.readInt();

nStartPos=newlong[nCount];

nEndPos=newlong[nCount];

for(inti=0;i

nStartPos[i]=input.readLong();

nEndPos[i]=input.readLong();

}

input.close();

}catch(IOExceptione){

e.printStackTrace();

}catch(Exceptione){

e.printStackTrace();

}

}

privatevoidprocessErrorCode(intnErrorCode){

System.err.println("ErrorCode:

"+nErrorCode);

}

publicvoidsiteStop(){

bStop=true;

for(inti=0;i

fileSplitterFetch[i].splitterStop();

}

}

创建继承Thread类的将要传输的网络文件分割线程类,文件名为FileSplitterFetch.java

importjava.io.IOException;

importjava.io.InputStream;

import.HttpURLConnection;

import.URL;

publicclassFileSplitterFetchextendsThread{

/*定义文件传输时使用的变量*/

StringsURL;

/*分段文件传输开始位置*/

longnStartPos;

/*分段文件传输结束位置*/

longnEndPos;

/*子线程ID*/

intnThreadID;

/*完成文件传输*/

booleanbDownOver=false;

/*停止文件传输*/

booleanbStop=false;

FileAccessfileAccess=null;

/**

*

*@paramsURL

*@paramsName

*@paramnStart

*@paramnEnd

*@paramid

*@throwsIOException

*/

publicFileSplitterFetch(StringsURL,StringsName,longnStart,longnEnd,intid)throwsIOException{

this.sURL=sURL;

this.nStartPos=nStart;

this.nEndPos=nEnd;

nThreadID=id;

//创建文件并打开

fileAccess=newFileAccess(sName,nStartPos);

}

/**

*

*/

publicvoidrun(){

while(nStartPos

bStop){

//创建连接

try{

URLurl=newURL(sURL);

HttpURLConnectionhttpConnection=(HttpURLConnection)url.openConnection();

httpConnection.setRequestProperty("User-Agent","NextFox");

StringsProperty="bytes="+nStartPos+"-";

httpConnection.setRequestProperty("RANGE",sProperty);

Utility.log(sProperty);

//创建输入流对象

InputStreaminput=httpConnection.getInputStream();

byte[]b=newbyte[1024];

intnRead;

while((nRead=input.read(b,0,1024))>0&&nStartPos

bStop){

nStartPos+=fileAccess.write(b,0,nRead);

}

Utility.log("Thread"+nThreadID+"isover!

");

bDownOver=true;

}catch(Exceptione){

e.printStackTrace();

}

}

}

/**

*处理和响应服务器头数据。

*@paramcon

*/

publicvoidlogResponseHead(HttpURLConnectioncon){

for(inti=1;;i++){

Stringheader=con.getHeaderFieldKey(i);

if(header!

=null){

Utility.log(header+":

"+con.getHeaderField(header));

}else{

break;

}

}

}

publicvoidsplitterStop(){

bStop=true;

}

}

创建设置和获取网络信息类,类名为SiteInfoBean.java

/**

*定义获取和设置相关文件类信息。

*@authorzhang

*/

publicclassSiteInfoBean{

/*定义URL变量*/

privateStringsSiteURL;

/*定义存文件路径变量*/

privateStringsFilePath;

/*定义文件名变量*/

privateStringsFileName;

/*定义传输文件计数器*/

privateintnSplitter;

publicSiteInfoBean(){

this("","","",5);

}

publicSiteInf

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 自然科学 > 物理

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2