您现在的位置是:首页 >

java中http断点续传的原理(1)

火烧 2023-01-28 18:02:29 1058
java中htt 断点续传的原理 1    一 断点续传的原理  其实断点续传的原理很简单 就是在Htt 的请求上和一般的下载有所不同而已   打个比方 浏览器请求服务器上的一个文时 所发出的请求如下

java中https断点续传的原理(1)  

  (一)断点续传的原理

  其实断点续传的原理很简单 就是在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 );

java中https断点续传的原理(1)

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

  ( 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 ();}

lishixinzhi/Article/program/Java/hx/201311/26964  
永远跟党走
  • 如果你觉得本站很棒,可以通过扫码支付打赏哦!

    • 微信收款码
    • 支付宝收款码