知识大全 用Java实现断点续传(HTTP)
Posted 文件
篇首语:谷要自长,人要自强。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 用Java实现断点续传(HTTP)相关的知识,希望对你有一定的参考价值。
用Java实现断点续传(HTTP) 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!
断点续传的原理
其实断点续传的原理很简单 就是在 Http 的请求上和一般的下载有所不同而已
打个比方 浏览器请求服务器上的一个文时 所发出的请求如下
假设服务器域名为 文件名为 down zip
GET /down zip HTTP/
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/ (patible; MSIE ; Windows NT )
Connection: Keep Alive
服务器收到请求后 按要求寻找请求的文件 提取文件的信息 然后返回给浏览器 返回信息如下
Content Length=
Accept Ranges=bytes
Date=Mon Apr : : GMT
ETag=W/ ca e c : b
Content Type=application/octet stream
Server=Microsoft IIS/
Last Modified=Mon Apr : : GMT
所谓断点续传 也就是要从文件已经下载的地方开始继续下载 所以在客户端浏览器传给 Web 服务器的时候要多加一条信息 从哪里开始
下面是用自己编的一个 浏览器 来传递请求信息给 Web 服务器 要求从 字节开始
GET /down zip HTTP/
User Agent: NetFox
RANGE: bytes=
Accept: text/ image/gif image/jpeg *; q= */*; q=
仔细看一下就会发现多了一行 RANGE: bytes=
这一行的意思就是告诉服务器 down zip 这个文件从 字节开始传 前面的字节不用传了
服务器收到这个请求以后 返回的信息如下
Content Length=
Content Range=bytes /
Date=Mon Apr : : GMT
ETag=W/ ca e c : b
Content Type=application/octet stream
Server=Microsoft IIS/
Last Modified=Mon Apr : : GMT
和前面服务器返回的信息比较一下 就会发现增加了一行
Content Range=bytes /
返回的代码也改为 了 而不再是 了
知道了以上原理 就可以进行断点续传的编程了
Java 实现断点续传的关键几点
( ) 用什么方法实现提交 RANGE: bytes=
当然用最原始的 Socket 是肯定能完成的 不过那样太费事了 其实 Java 的 net 包中提供了这种功能 代码如下
URL url = new URL( );
HttpURLConnection Connection = (HttpURLConnection)url openConnection();
// 设置 User Agent
( User Agent NetFox );
// 设置断点续传的开始位置
( RANGE bytes= );
// 获得输入流
InputStream input = ();
从输入流中取出的字节流就是 down zip 文件从 开始的字节流 大家看 其实断点续传用 Java 实现起来还是很简单的吧 接下来要做的事就是怎么保存获得的流到文件中去了
保存文件采用的方法
我采用的是 IO 包中的 RandAccessFile 类
操作相当简单 假设从 处开始保存文件 代码如下
RandomAccess oSavedFile = new RandomAccessFile( down zip rw );
long nPos = ;
// 定位文件指针到 nPos 位置
oSavedFile seek(nPos);
byte[] b = new byte[ ];
int nRead;
// 从输入流中读入字节流 然后写到文件中
while((nRead=input read(b )) > )
oSavedFile write(b nRead);
怎么样 也很简单吧 接下来要做的就是整合成一个完整的程序了 包括一系列的线程控制等等
断点续传内核的实现
主要用了 个类 包括一个测试类
SiteFileFetch java 负责整个文件的抓取 控制内部线程 (FileSplitterFetch 类 )
FileSplitterFetch java 负责部分文件的抓取
FileAccess java 负责文件的存储
SiteInfoBean java 要抓取的文件的信息 如文件保存的目录 名字 抓取文件的 URL 等
Utility java 工具类 放一些简单的方法
TestMethod java 测试类
下面是源程序
/*
/*
* SiteFileFetch java
*/
package NetFox;
import java io *;
import *;
public class SiteFileFetch extends Thread
SiteInfoBean siteInfoBean = null; // 文件信息 Bean
long[] nStartPos; // 开始位置
long[] nEndPos; // 结束位置
FileSplitterFetch[] fileSplitterFetch; // 子线程对象
long nFileLength; // 文件长度
boolean bFirst = true; // 是否第一次取文件
boolean bStop = false; // 停止标志
File tmpFile; // 文件下载的临时信息
DataOutputStream output; // 输出到文件的输出流
public SiteFileFetch(SiteInfoBean bean) throws IOException
siteInfoBean = bean;
//tmpFile = File createTempFile ( zhong new File(bean getSFilePath()));
tmpFile = new File(bean getSFilePath()+File separator + bean getSFileName()+ );
if(tmpFile exists ())
bFirst = false;
read_nPos();
else
nStartPos = new long[bean getNSplitter()];
nEndPos = new long[bean getNSplitter()];
public void run()
// 获得文件长度
// 分割文件
// 实例 FileSplitterFetch
// 启动 FileSplitterFetch 线程
// 等待子线程返回
try
if(bFirst)
nFileLength = getFileSize();
if(nFileLength == )
System err println( File Length is not known! );
else if(nFileLength == )
System err println( File is not access! );
else
for(int i= ;i<nStartPos length;i++)
nStartPos[i] = (long)(i*(nFileLength/nStartPos length));
for(int i= ;i<nEndPos length ;i++)
nEndPos[i] = nStartPos[i+ ];
nEndPos[nEndPos length ] = nFileLength;
// 启动子线程
fileSplitterFetch = new FileSplitterFetch[nStartPos length];
for(int i= ;i<nStartPos length;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 ] = new FileSplitterFetch(siteInfoBean getSSiteURL()
siteInfoBean getSFilePath() + File separator
+ siteInfoBean getSFileName() nPos[nPos length ] nFileLength nPos length );
// Utility log( Thread +(nPos length ) + nStartPos = +nPos[nPos length ]+
nEndPos = + nFileLength);
// fileSplitterFetch[nPos length ] start();
// 等待子线程结束
//int count = ;
// 是否结束 while 循环
boolean breakWhile = false;
while(!bStop)
write_nPos();
Utility sleep( );
breakWhile = true;
for(int i= ;i<nStartPos length;i++)
if(!fileSplitterFetch[i] bDownOver)
breakWhile = false;
break;
if(breakWhile)
break;
//count++;
//if(count> )
// siteStop();
System err println( 文件下载结束! );
catch(Exception e)e printStackTrace ();
// 获得文件长度
public long getFileSize()
int nFileLength = ;
try
URL url = new URL(siteInfoBean getSSiteURL());
HttpURLConnection Connection = (HttpURLConnection)url openConnection ();
( User Agent NetFox );
int responseCode=();
if(responseCode>= )
processErrorCode(responseCode);
return ; // represent access is error
String sHeader;
for(int i= ;;i++)
//DataInputStream in = new DataInputStream( ());
//Utility log(in readLine());
sHeader=(i);
if(sHeader!=null)
if(sHeader equals( Content Length ))
nFileLength = Integer parseInt((sHeader));
break;
else
break;
catch(IOException e)e printStackTrace ();
catch(Exception e)e printStackTrace ();
Utility log(nFileLength);
return nFileLength;
// 保存下载信息(文件指针位置)
private void write_nPos()
try
output = new DataOutputStream(new FileOutputStream(tmpFile));
output writeInt(nStartPos length);
for(int i= ;i<nStartPos length;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 ();
// 读取保存的下载信息(文件指针位置)
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= ;i<nStartPos length;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);
// 停止文件下载
public void siteStop()
bStop = true;
for(int i= ;i<nStartPos length;i++)
fileSplitterFetch[i] splitterStop();
/*
**FileSplitterFetch java
*/
package NetFox;
import java io *;
import *;
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 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 Connection = (HttpURLConnection)url openConnection ();
( User Agent NetFox );
String sProperty = bytes= +nStartPos+ ;
( RANGE sProperty);
Utility log(sProperty);
InputStream input = ();
//logResponseHead(Connection);
byte[] b = new byte[ ];
int nRead;
while((nRead=input read(b )) > && nStartPos < nEndPos
&& !bStop)
nStartPos += fileAccessI write(b nRead);
//if(nThreadID == )
// Utility log( nStartPos = + nStartPos + nEndPos = + nEndPos);
Utility log( Thread + nThreadID + is over! );
bDownOver = true;
//nPos = fileAccessI write (b nRead);
catch(Exception e)e printStackTrace ();
// 打印回应的头信息
public void logResponseHead(HttpURLConnection con)
for(int i= ;;i++)
String header=con getHeaderFieldKey(i);
if(header!=null)
//responseHeaders put(header (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( );
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 = ;
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
this( );
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/weblogic b _win exe
try
SiteInfoBean bean = new SiteInfoBean(
L:\\\\temp weblogic b _win exe );
//SiteInfoBean bean = new SiteInfoBean( L:\\\\temp
weblogic b _win exe );
SiteFileFetch fileFetch = new SiteFileFetch(bean);
fileFetch start();
catch(Exception e)e printStackTrace ();
public static void main(String[] args)
new TestMethod();
cha138/Article/program/Java/hx/201311/26131
相关参考
用Java实现HTTP断点续传功能(2) 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! //启动
/** *authorannegu *date */ annegu做了一个简单的Http多线程的下载程序来讨论一下多线程并发下载以及断点续传的问题 这个程序的功能就是可以分多个线程从目标
(一)断点续传的原理 其实断点续传的原理很简单就是在Http的请求上和一般的下载有所不同而已 打个比方浏览器请求服务器上的一个文时所发出的请求如下 假设服务器域名为文件名为downzip
Java网络编程从入门到精通(24):实现HTTP断点续传下载工具(附源代码) 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,
/* **SiteFileFetchjava */ packageNetFox; importjavaio*; import*; publicclassSiteFileFetc
如何使用.NET实现断点续传功能 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 顾名思义断点续传
使用VisualC#实现断点续传 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! &nbs
PHP下载远程文件类(支持断点续传) 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! PHP下载远
在vs中我们可以直接用表达式数值型比较直接用操作符即可 如i==i<; 但是字符型比较呢? 加入我们有一个名为string的变量定义如下: char*string=Two; 设置断
Java获取Http响应Header信息 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 本文中演