断点续传的原理(转)
  zt from http://www.chinajavaworld.com  (一)断点续传的原理  其实断点续传的原理很简单,就是在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  ();  //设置User-Agent  httpConnection.setRequestProperty("User-Agent","NetFox");  //设置断点续传的开始位置  httpConnection.setRequestProperty("RANGE","bytes=2000070");  //获得输入流  InputStream input = httpConnection.getInputStream();  从输入流中取出的字节流就是down.zip文件从2000070开始的字节流。  大家看,其实断点续传用Java实现起来还是很简单的吧。  接下来要做的事就是怎么保存获得的流到文件中去了。  保存文件采用的方法。  我采用的是IO包中的RandAccessFile类。  操作相当简单,假设从2000070处开始保存文件,代码如下:  RandomAccess oSavedFile = new RandomAccessFile("down.zip","rw");  long nPos = 2000070;  //定位文件指针到nPos位置  oSavedFile.seek(nPos);  byte[] b = new byte[1024];  int nRead;  //从输入流中读入字节流,然后写到文件中  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; //文件信息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","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()  {  //获得文件长度  //分割文件  //实例FileSplitterFetch  //启动FileSplitterFetch线程  //等待子线程返回  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 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();  //等待子线程结束  //int count = 0;  //是否结束while循环  boolean breakWhile = false;  while(!bStop)  {  write_nPos();  Utility.sleep(500);  breakWhile = true;  for(int i=0;i4)  // siteStop();  }  System.err.println("文件下载结束!");  }  catch(Exception e){e.printStackTrace ();}  }  //获得文件长度  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; //-2 represent access is error  }  String sHeader;  for(int i=1;;i++)  {  //DataInputStream in = new DataInputStream(httpConnection.getInputStream ());  //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;  }  //保存下载信息(文件指针位置)  private void write_nPos()  {  try{  output = new DataOutputStream(new FileOutputStream(tmpFile));  output.writeInt(nStartPos.length);  for(int i=0;iDataInputStream(new FileInputStream(tmpFile));  int nCount = input.readInt();  nStartPos = new long[nCount];  nEndPos = new long[nCount];  for(int i=0;i 0 & & nStartPos < nEndPos && !bStop)  {  nStartPos += fileAccessI.write(b,0,nRead);  //if(nThreadID == 1)  // Utility.log("nStartPos = " + nStartPos + ", nEndPos = " + nEndPos);  }  Utility.log("Thread " + nThreadID + " is over!");  bDownOver = true;  //nPos = fileAccessI.write (b,0,nRead);  }  catch(Exception e){e.printStackTrace ();}  }  }  //打印回应的头信息  public void logResponseHead(HttpURLConnection con)  {  for(int i=1;;i++)  {  String header=con.getHeaderFieldKey(i);  if(header!=null)  //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; //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 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: emp","weblogic60b2_win.exe",5);  //SiteInfoBean bean = new SiteInfoBean("http://localhost:8080/down.zip"," L: emp","weblogic60b2_win.exe",5);  SiteFileFetch fileFetch = new SiteFileFetch(bean);  fileFetch.start();  }  catch(Exception e){e.printStackTrace ();}  }  public static void main(String[] args)  {  new TestMethod();  }  }本文来自:http://www.linuxpk.com/5163.html--&gtlinux电子图书免费下载和技术讨论基地·上一篇:高级扫描技术及原理介绍·下一篇:vmware网络设置三:理解虚拟网络的类型

 
     最新更新
·隐藏/etc目录·PC服务器中的“1U/2U”中“U”的含义·信号集合·单网卡架设NAT过程·关于Linux下网卡的一些技术信息·uptime作弊方法·进程查看·网络层访问权限控制技术ACL详解·常见端口表汇总·IP基础--1.IP地址·profile,rcfile的搜索执行顺序·IP基础--3.ARP协定·IP基础--2.DHCP协定·IP基础--5.DNS协定·IP基础--4.RIP协定·判断华为中低端交换机是二层还是三层的简单方法·目录列表小技巧·ubuntu关闭ipv6,提高dns解析速度·网络组建大全(包括企业网、校园网、网吧和基础知识)·xinetd使用指南(二)·Linux下的网络邻居软件大全·44个路由器知识要点·linux下用802.1x客户端上网·网络监控-iptraf安装配置使用中文文档·Linux网络应用问答·xinetd使用指南(一)·网络词典[U~Z]·linux网络服务器配置基础·端口基础常识大全贴·man内容的屏幕拷贝

关于我们 | 联系方式 | 广告合作 | 诚聘英才 | 网站地图 | 网址大全 | 友情链接 | 免费注册

Copyright © 2004 - 2007 All Rights Reserved

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/14102/viewspace-117227/,如需转载,请注明出处,否则将追究法律责任。

0
0
分享到:

上一篇: Linux网络的IPv6应用(1)(转)
下一篇: 中小网站如何对付DoS攻击(中级)(转)

请登录后发表评论 登录

全部评论
<%=items[i].createtime%>

<%=items[i].content%>

<%if(items[i].items.items.length) { %>

<%for(var j=0;j

<%=items[i].items.items[j].createtime%> 回复

<%=items[i].items.items[j].username%>   回复   <%=items[i].items.items[j].tousername%>: <%=items[i].items.items[j].content%>

<%}%> <%if(items[i].items.total > 5) { %>

还有<%=items[i].items.total-5%>条评论) data-count=1 data-flag=true>点击查看

<%}%>

<%}%> <%}%>

ilg

注册时间:2002-06-18

  • 博文量

    1715

  • 访问量
    1297601

最新文章

  • Solaris 图形窗口配置(转)
  • WPSOffice双面文档打印边距设置(转)
  • OfficeWord2007图片编辑功能使用教程(转)
  • IE技巧两则(转)
  • 用Iproute2配置隧道(转)
  • 用FAQGenie迅速制作“常见问答”网页(转)
  • openoffice2.0输出带多级书签的PDF文档(转)
  • WordXP巧画禁烟标志(转)
  • Linux中防御垃圾邮件的方法(转)
  • Excel:轻松查看数据记录(转)

支持我们 作者招募 用户协议 FAQ Contact Us

北京盛拓优讯信息技术有限公司. 版权所有  京ICP备09055130号-4  北京市公安局海淀分局网监中心备案编号:11010802021510

广播电视节目制作经营许可证(京) 字第1234号 中国互联网协会会员

转载于:http://blog.itpub.net/14102/viewspace-117227/

断点续传的原理(转)相关推荐

  1. JAVA编程技巧之如何实现HTTP的断点续传(原理篇)

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 虽然断点 ...

  2. 断点续传的原理剖析与实例讲解

    断点续传的原理剖析与实例讲解 本文所要讲的是Android断点续传的内容,以实例的形式进行了详细介绍. 一.断点续传的原理 其实断点续传的原理很简单,就是在http的请求上和一般的下载有所不同而已. ...

  3. Java后端处理video快进快退播放以及断点续传的原理和代码

    video 快进快退的原理: 通过对所在服务器上的流媒体进行skip操作,然后再response的header里设置相应的Content-Range以及其他属性,来控制视频流的快进快退的功能. 断点续 ...

  4. http断点续传java_java中http断点续传的原理

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

  5. java断点续传原理_java 文件断点续传实现原理

    关键字: RandomAccessFile 一.作用: 随机流(RandomAccessFile)不属于IO流,支持对文件的读取和写入随机访问. 二.随机访问文件原理: 首先把随机访问的文件对象看作存 ...

  6. java写入写出文件的原理_Java文件断点续传实现原理解析

    一.作用: 随机流(RandomAccessFile)不属于IO流,支持对文件的读取和写入随机访问. 二.随机访问文件原理: 首先把随机访问的文件对象看作存储在文件系统中的一个大型 byte 数组,然 ...

  7. Android 断点续传实现原理

    转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/120956134 本文出自[赵彦军的博客] 文章目录 下载原理 断点续传原理 1.j ...

  8. http断点续传的原理

    --------------先讲原理,如下:------------------ 举一个详细的例子: 一般场景,要访问的域名:www.jizhuomi.com/android,文件名为down.zip ...

  9. Android多线程断点续传下载原理及实现,移动开发工程师简历

    RandomAccessFile 文件写入 下面再讲讲文件写入问题,由于我们是多线程下载,因此文件并不是每次都是从前往后一个个字节写入的,随时可能在文件的任何一个地方写入数据.因此我们需要能够在文件的 ...

最新文章

  1. 【Java从0到架构师(1),Java中高级面试题总结(全面)
  2. 给博客园加一个会动的小人-spig.js
  3. go去掉最后一个字符_Go语言去除字符串中的指定字符
  4. Python中各个模块的介绍和使用
  5. “宅家十大热销商品”榜单:确认过眼神,都是自己剪头发的人
  6. SQL索引管理器——用于SQL Server和Azure上的索引维护的免费G​​UI工具
  7. linux系统修复找不到原安装,Linux 系统用安装盘来修复GRUB 详解
  8. springMVC中ajax的实现
  9. 中国智能汽车行业市场需求趋势与发展战略规划建议报告2022-2028年版
  10. 北大青鸟网络工程师benet培训招生问答
  11. http 405原因
  12. PowerBI中常用的DAX函数
  13. qiankun 2.x 运行时沙箱 源码分析
  14. 如何用天干地支计算年月日时?
  15. 那一年,我与电脑结下了不解之缘
  16. dd命令(dd命令制作镜像)
  17. 达内教育python培训
  18. 基于javaweb的新闻发布系统(java+springboot+ssm+mysql)
  19. webpack配置---设置快捷打包和浏览器自动刷新
  20. MacOS 12.0 Monterey Beta5 (21A5304g) 三分区原版黑苹果镜像

热门文章

  1. 干接点信号_百度百科
  2. Redis【10】-Redis发布订阅
  3. 快速对齐word中目录的页码|容易上手的方法
  4. 知网是如何判断论文重复的?
  5. STM32G474的启动模式NRST引脚特性
  6. e与phi不互素 --- 五道题详记
  7. Android Studio飘红错误
  8. 【精品】身份证操作工具类
  9. 怎样利用关键词查排名的工具找到行业相关网站
  10. USACO-Section 1.2 Daul Palindromes[...]