




已阅读5页,还剩9页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Java实现断点续传原理(参考代码) (注:类用红色字体表示,所需类已经添加至压缩包) 代码部分-类的字体, Package的字体,import导包的字体 中文注释均高亮上色,每个类前都有类的注释/*/格式(一)断点续传的原理 其实断点续传的原理,就是在Http的请求上和一般的下载有所不同而已。打个比方,浏览器请求服务器上的一个文时,所发出的请求如下:假设服务器域名为,文件名为down.zip。GET /down.zip HTTP/1.1Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/msword, application/vnd.ms-powerpoint, */*Accept-Language: zh-cnAccept-Encoding: gzip, deflateUser-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)Connection: Keep-Alive服务器收到请求后,按要求寻找请求的文件,提取文件的信息,然后返回给浏览器,返回信息如下:200Content-Length=106786028Accept-Ranges=bytesDate=Mon, 30 Apr 2001 12:56:11 GMTETag=W/02ca57e173c11:95bContent-Type=application/octet-streamServer=Microsoft-IIS/5.0Last-Modified=Mon, 30 Apr 2001 12:56:11 GMT所谓断点续传,也就是要从文件已经下载的地方开始继续下载。所以在客户端浏览器传给Web服务器的时候要多加一条信息-从哪里开始。下面是用自己编的一个浏览器来传递请求信息给Web服务器,要求从2000070字节开始。GET /down.zip HTTP/1.0User-Agent: NetFoxRANGE: bytes=2000070-Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2仔细看一下就会发现多了一行RANGE: bytes=2000070-这一行的意思就是告诉服务器down.zip这个文件从2000070字节开始传,前面的字节不用传了。服务器收到这个请求以后,返回的信息如下:206Content-Length=106786028Content-Range=bytes 2000070-106786027/106786028Date=Mon, 30 Apr 2001 12:55:20 GMTETag=W/02ca57e173c11:95bContent-Type=application/octet-streamServer=Microsoft-IIS/5.0Last-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(/down.zip);HttpURLConnection httpConnection = (HttpURLConnection)url.openConnection();/设置User-AgenthttpConnection.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 byte1024;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测试类。 下面是参考源码:(6个类我已经单独压缩成文件,放在NetFox package下)效果图如下:/*SiteFileFetch.java*/package NetFox;import java.io.*;import .*;public class SiteFileFetch extends Thread SiteInfoBean siteInfoBean = null; /文件信息Beanlong nStartPos; /开始位置long nEndPos; /结束位置FileSplitterFetch fileSplitterFetch; /子线程对象long nFileLength; /文件长度boolean bFirst = true; /是否第一次取文件boolean bStop = false; /停止标志File tmpFile; /文件下载的临时信息DataOutputStream output; /输出到文件的输出流public SiteFileFetch(SiteInfoBean bean) throws IOExceptionsiteInfoBean = 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();elsenStartPos = new longbean.getNSplitter();nEndPos = new longbean.getNSplitter();public void run()/获得文件长度/分割文件/实例FileSplitterFetch/启动FileSplitterFetch线程/等待子线程返回tryif(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!);elsefor(int i=0;inStartPos.length;i+)nStartPosi = (long)(i*(nFileLength/nStartPos.length);for(int i=0;inEndPos.length-1;i+)nEndPosi = nStartPosi+1;nEndPosnEndPos.length-1 = nFileLength;/启动子线程fileSplitterFetch = new FileSplitterFetchnStartPos.length;for(int i=0;inStartPos.length;i+)fileSplitterFetchi = new FileSplitterFetch(siteInfoBean.getSSiteURL(),siteInfoBean.getSFilePath() + File.separator + siteInfoBean.getSFileName(),nStartPosi,nEndPosi,i);Utility.log(Thread + i + , nStartPos = + nStartPosi + , nEndPos = + nEndPosi);fileSplitterFetchi.start();/ fileSplitterFetchnPos.length-1 = new FileSplitterFetch(siteInfoBean.getSSiteURL(),siteInfoBean.getSFilePath() + File.separator + siteInfoBean.getSFileName(),nPosnPos.length-1,nFileLength,nPos.length-1);/ Utility.log(Thread + (nPos.length-1) + , nStartPos = + nPosnPos.length-1 + ,nEndPos = + nFileLength);/ fileSplitterFetchnPos.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;tryURL 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 errorString 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;elsebreak;catch(IOException e)e.printStackTrace ();catch(Exception e)e.printStackTrace ();Utility.log(nFileLength);return nFileLength;/保存下载信息(文件指针位置)private void write_nPos()tryoutput = new DataOutputStream(new FileOutputStream(tmpFile);output.writeInt(nStartPos.length);for(int i=0;inStartPos.length;i+)/ output.writeLong(nPosi);output.writeLong(fileSplitterFetchi.nStartPos);output.writeLong(fileSplitterFetchi.nEndPos);output.close();catch(IOException e)e.printStackTrace ();catch(Exception e)e.printStackTrace ();/读取保存的下载信息(文件指针位置)private void read_nPos()tryDataInputStream input = new DataInputStream(new FileInputStream(tmpFile);int nCount = input.readInt();nStartPos = new longnCount;nEndPos = new longnCount;for(int i=0;inStartPos.length;i+)nStartPosi = input.readLong();nEndPosi = 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=0;inStartPos.length;i+)fileSplitterFetchi.splitterStop();/*FileSplitterFetch.java*/package NetFox;import java.io.*;import .*;public class FileSplitterFetch extends Thread String sURL; /File URLlong nStartPos; /File Snippet Start Positionlong nEndPos; /File Snippet End Positionint nThreadID; /Threads IDboolean bDownOver = false; /Downing is overboolean bStop = false; /Stop identicalFileAccessI fileAccessI = null; /File Access interfacepublic FileSplitterFetch(String sURL,String sName,long nStart,long nEnd,int id) throws IOExceptionthis.sURL = sURL;this.nStartPos = nStart;this.nEndPos = nEnd;nThreadID = id;fileAccessI = new FileAccessI(sName,nStartPos);public void run()while(nStartPos 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);elsebreak;public void splitterStop()bStop = true;/*FileAccessI.java(类)*/package NetFox;import java.io.*;public class FileAccessI implements SerializableRandomAccessFile oSavedFile;long nPos;public FileAccessI() throws IOExceptionthis(,0);public FileAccessI(String sName,long nPos) throws IOExceptionoSavedFile = new RandomAccessFile(sName,rw);this.nPos = nPos;oSavedFile.seek(nPos);public synchronized int write(byte b,int nStart,int nLen)int n = -1;tryoSavedFile.write(b,nStart,nLen);n = nLen;catch(IOException e)e.printStackTrace ();return n;/*SiteInfoBean.java*/package NetFox;public class SiteInfoBean private String sSiteURL; /Sites URLprivate String sFilePath; /Saved Files Pathprivate String sFileName; /Saved Files Nameprivate int nSplitter; /Count of Splited Downloading Filepublic SiteInfoBean()/default value of nSplitter is 5this(,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
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年度医疗护理员理论考核试题(+答案)
- 2025年初级电焊工考试题库(附答案)
- 解除房屋租赁合同协议(标准版)6篇
- 小龙虾养老食品创新创业项目商业计划书
- 广告传媒创意中心创新创业项目商业计划书
- 海洋主题游乐园设施升级创新创业项目商业计划书
- 政务消防管理系统创新创业项目商业计划书
- 水果风味果酱夹心巧克力创新创业项目商业计划书
- 油料作物功能纤维创新创业项目商业计划书
- 智慧农业与农村互联网金融创新创业项目商业计划书
- GB 9743-1997轿车轮胎
- DB225118-2022建筑工程资料管理标准
- USCAR培训资料完整版经典培训教材课件
- 涂漆检验报告(面漆)
- 制药工程专业导论03.中药制药课件
- 肿瘤生物免疫治疗及护理-课件
- 小学数学四年级上册《数对》课件
- 高中英语选择性必修一 Unit 2 Assessing your progress(34张)
- 液压传动全套ppt课件(完整版)
- 《基础统计》教学案例“郑州市大瓶装纯水市场调查”统计应用案例
- 南瑞继保后台监控使用厂家培训版本
评论
0/150
提交评论