基本模拟了迅雷下载的原理
本次功能用java实现 :
利用txt文件记录下载的状态 如果在安卓端的话 可以改成用数据库记录下载状态
本程序可以扩展为具有良好用户体验的 下载程序
package mutiDownload; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.RandomAccessFile; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; /** * 多线程断点下载文件 * * @author Administrator * */ public class BreakpointDoloadDemo { public static int threadcount = 3; public static int threadRunning = 3; public static void main(String[] args) throws IOException { // TODO Auto-generated method stub // 获取服务器上的文件长度,在本地创建一个和服务器上的文件一样大的临时文件 String pathString = "http://192.168.1.84:8091/androidServer/test.mkv"; URL url = new URL(pathString); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setConnectTimeout(5000); connection.setRequestMethod("GET"); int code = connection.getResponseCode(); if (code == 200) { // 请求成功 int length = connection.getContentLength(); System.out.println("文件长度:" + length); RandomAccessFile ref = new RandomAccessFile("test.mkv", "rwd"); // 指定创建的临时文件的长度 ref.setLength(length); ref.close(); int blocksize = length / threadcount; for (int threadId = 1; threadId <= threadcount; threadId++) { int startIndex = (threadId - 1) * blocksize; // 线程开始位置 int endIndex = threadId * blocksize - 1; if (threadId == threadcount) { endIndex = length; } System.out.println("线程" + threadId + "下载---" + startIndex + "-->" + endIndex); new Downhread(threadId, startIndex, endIndex, pathString) .start(); ; } } else { System.out.println("服务器错误"); } } /** * 下载文件子线程 * * @author Administrator * */ public static class Downhread extends Thread { private int threadId; private int startIndex; private int endIndex; private String path; /** * * @param threadId * 线程id * @param startIndex * 线程下载的开始位置 * @param endIndex * @param path * 下载文件在服务器上的位置 */ public Downhread(int threadId, int startIndex, int endIndex, String path) { super(); this.threadId = threadId; this.startIndex = startIndex; this.endIndex = endIndex; this.path = path; } @Override public void run() { // TODO Auto-generated method stub // super.run(); try { //检查是否存在记录下载长度的文件,如果存在读取文件的数据 File tempFile=new File(threadId+".txt"); if(tempFile.exists()&&tempFile.length()>0){ FileInputStream fis=new FileInputStream(tempFile); byte [] temp=new byte[1024]; int leng=fis.read(temp); String downloadLen=new String(temp,0,leng); int downloadInt=Integer.parseInt(downloadLen); startIndex=downloadInt; //修改下载的真实开始位置 } URL url = new URL(path); HttpURLConnection connection = (HttpURLConnection) url .openConnection(); connection.setConnectTimeout(5000); connection.setRequestMethod("GET"); connection.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex); System.out.println("线程真实下载位置:" + threadId + "startIndex:" + startIndex+"-->"+endIndex); int code = connection.getResponseCode(); System.out.println("code:" + code); // if(code==200){ //请求成功 // // } InputStream is = connection.getInputStream(); RandomAccessFile raf = new RandomAccessFile("test.mkv", "rwd"); // 写文件的时候指定从哪个位置开始写 raf.seek(startIndex); int len = 0; byte[] buffer = new byte[1024]; int total = 0; // 已经下载的数据长度 // File file=new File(threadId+".txt"); //作用:记录当前线程下载的数据长度 while ((len = is.read(buffer)) != -1) { RandomAccessFile file = new RandomAccessFile(threadId + ".txt", "rwd"); raf.write(buffer, 0, len); total += len; //System.out.println("线程:" + threadId + "total:" + total); file.write(String.valueOf(total+startIndex).getBytes()); //记录下载的位置 file.close(); } is.close(); raf.close(); System.out.println("线程:" + threadId + "下载完毕了..."); // File delfile =new File(threadId+ ".txt"); // delfile.delete(); //当线程下载完毕后清除记录文件 } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally{ threadRunning--; if(threadRunning==0){ //所有线程执行完毕 for(int i=0;i<=3;i++){ File file =new File(i+ ".txt"); file.delete(); } System.out.println("文件下载完毕,删除所有记录文件"); } } } } }