知识大全 用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)

用Java实现HTTP断点续传功能(2)  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  //启动

知识大全 用java多线程断点续传实践

  /**  *authorannegu  *date  */  annegu做了一个简单的Http多线程的下载程序来讨论一下多线程并发下载以及断点续传的问题  这个程序的功能就是可以分多个线程从目标

知识大全 java中http断点续传的原理(1)

  (一)断点续传的原理  其实断点续传的原理很简单就是在Http的请求上和一般的下载有所不同而已  打个比方浏览器请求服务器上的一个文时所发出的请求如下  假设服务器域名为文件名为downzip  

知识大全 实现HTTP断点续传下载工具(附源代码)

Java网络编程从入门到精通(24):实现HTTP断点续传下载工具(附源代码)  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,

知识大全 http断点续传简单实现

  /*  **SiteFileFetchjava  */  packageNetFox;  importjavaio*;  import*;      publicclassSiteFileFetc

知识大全 如何使用.NET实现断点续传功能

如何使用.NET实现断点续传功能  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  顾名思义断点续传

知识大全 使用Visual C#实现断点续传

使用VisualC#实现断点续传  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! &nbs

知识大全 PHP 下载远程文件类(支持断点续传)

PHP下载远程文件类(支持断点续传)  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  PHP下载远

知识大全 vs2010根据字符串内容添加断点的方法介绍

  在vs中我们可以直接用表达式数值型比较直接用操作符即可  如i==i<;  但是字符型比较呢?  加入我们有一个名为string的变量定义如下:  char*string=Two;  设置断

知识大全 Java获取Http响应Header信息

Java获取Http响应Header信息  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  本文中演