爱阳阳 发表于 2013-1-29 22:31:53

用 Java 实现断点续传-实现 (HTTP)

断点续传内核的实现
主要用了 6 个类,包括一个测试类。
SiteFileFetch.java 负责整个文件的抓取,控制内部线程 (FileSplitterFetch 类 )。
FileSplitterFetch.java 负责部分文件的抓取。
FileAccess.java 负责文件的存储。
SiteInfoBean.java 要抓取的文件的信息,如文件保存的目录,名字,抓取文件的 URL 等。
Utility.java 工具类,放一些简单的方法。
TestMethod.java 测试类。
下面是源程序:
package cn.hiservice.download;import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.net.HttpURLConnection;import java.net.URL;/** ** @author Administrator **/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 IOException {siteInfoBean = bean;tmpFile = new File(bean.getSFilePath() + File.separator+ bean.getSFileName() + ".info");System.out.println(tmpFile);if (tmpFile.exists()) {bFirst = false;read_nPos();} else {nStartPos = new long;nEndPos = new long;}}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 < nStartPos.length; i++) {nStartPos = (long) (i * (nFileLength / nStartPos.length));}for (int i = 0; i < nEndPos.length - 1; i++) {nEndPos = nStartPos;}nEndPos = nFileLength;}}// 启动子线程fileSplitterFetch = new FileSplitterFetch;for (int i = 0; i < nStartPos.length; i++) {fileSplitterFetch = new FileSplitterFetch(siteInfoBean.getSSiteURL(), siteInfoBean.getSFilePath()+ File.separator + siteInfoBean.getSFileName(),nStartPos, nEndPos, i);Utility.log("Thread " + i + " , nStartPos = " + nStartPos+ ", nEndPos = " + nEndPos);fileSplitterFetch.start();}/* * fileSplitterFetch = new * FileSplitterFetch(siteInfoBean.getSSiteURL(), * siteInfoBean.getSFilePath() + File.separator + * siteInfoBean.getSFileName * (),nPos,nFileLength,nPos.length-1); */// Utility.log("Thread " +(nPos.length-1) +// ",nStartPos = "+nPos+",// nEndPos = " + nFileLength);// fileSplitterFetch.start();// 等待子线程结束// int count = 0;// 是否结束 while 循环boolean breakWhile = false;while (!bStop) {write_nPos();Utility.sleep(500);breakWhile = true;for (int i = 0; i < nStartPos.length; i++) {if (!fileSplitterFetch.bDownOver) {breakWhile = false;break;}}if (breakWhile)break;// count++;// if(count>4)// 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;}} elsebreak;}} 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; i < nStartPos.length; i++) {// output.writeLong(nPos);output.writeLong(fileSplitterFetch.nStartPos);output.writeLong(fileSplitterFetch.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;nEndPos = new long;for (int i = 0; i < nStartPos.length; i++) {nStartPos = input.readLong();nEndPos = 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; i < nStartPos.length; i++)fileSplitterFetch.splitterStop();}public static void main(String[] args) {new TestMethod();}}
package cn.hiservice.download;/***FileSplitterFetch.java*/import java.io.*;import java.net.*;public class FileSplitterFetch extends Thread {String sURL; // File URLlong nStartPos; // File Snippet Start Positionlong nEndPos; // File Snippet End Positionint nThreadID; // Thread's 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 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 httpConnection = (HttpURLConnection) url.openConnection();httpConnection.setRequestProperty("User-Agent", "NetFox");String sProperty = "bytes=" + nStartPos + "-";httpConnection.setRequestProperty("RANGE", sProperty);Utility.log(sProperty);InputStream input = httpConnection.getInputStream();// logResponseHead(httpConnection);byte[] b = new byte;int nRead;while ((nRead = input.read(b, 0, 1024)) > 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;}}
package cn.hiservice.download;public class SiteInfoBean {private String sSiteURL; // Site's URLprivate String sFilePath; // Saved File's Pathprivate String sFileName; // Saved File's 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 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;}}
package cn.hiservice.download;/***FileAccess.java*/import java.io.*;public class FileAccessI implements Serializable {private static final long serialVersionUID = 1L;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;}}
package cn.hiservice.download;/***Utility.java*/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);}}
package cn.hiservice.download;import org.junit.Test;/***TestMethod.java*/public class TestMethod {publicTestMethod() { try {SiteInfoBean bean = new SiteInfoBean("http://localhost:8088/FileDownLoad/Ducati_Windows7.themepack", "D:\\temp","Ducati_Windows7.themepack", 3);SiteFileFetch fileFetch = new SiteFileFetch(bean);fileFetch.start();} catch (Exception e) {e.printStackTrace();}}}
页: [1]
查看完整版本: 用 Java 实现断点续传-实现 (HTTP)