1,把阿里旺旺传到服务器上

2,分3个线程,分别下载不同位置的文件

3,用3个文件记录每次下载的位置,停止后再次下载时,直接从已下载的位置开始继续下载,当文件下载完成后删除记录的文件

Java socket断点续传文件 java文件下载断点续传_文件下载

测试成功,下面是实现代码:

package com.zhuyu.utils;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
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 zhuyu
 * 支持断点续传
 */
public class MultiDownload {
	//线程数量
	public static int threadCount = 3;
	//记录线程下载文件标识,所有线程下载完成则文件下载完成
	public static int runningThread = threadCount;
	
	public static void main(String[] args) throws MalformedURLException {		
		//1.获取文件大小,创建一个和服务器文件对应的临时文件
		//2.计算分配几个线程下载服务器资源,知道每个线程下载文件的位置
		//3.开启多线程  开始位置:(线程id-1)* 每一块大小   结束位置:(线程id* 每一块大小)-1
		String path = "http://192.168.20.117:8888/AliIM2014.exe";
		URL url = new URL(path);
		try {
			String newFileName = path.substring(path.lastIndexOf("/") + 1);
			HttpURLConnection conn = (HttpURLConnection) url.openConnection();
			conn.setConnectTimeout(5000);
			conn.setRequestMethod("GET");
			int code = conn.getResponseCode();
			if(code == 200){
				//服务器文件总大小
				int length = conn.getContentLength();
				int blockSize = length / threadCount; //每一块的大小
				//在客户端本地创建一个跟服务端大小一致的临时文件
				RandomAccessFile raf = new RandomAccessFile(newFileName,"rwd");
				raf.setLength(length);
				raf.close();
				
				for(int threadId=1;threadId <= threadCount ; threadId ++){
					int startIndex = (threadId - 1) * blockSize;
					int endIndex = (threadId * blockSize) - 1;
					if(threadId == threadCount){ //如果线程是最后一个,则结束位置为最后位置
						endIndex = length ;
					}
					//下载文件
					new DownloadFileThread(path, startIndex, endIndex, threadId){}.start();
				}
				
			}else{
				System.out.println("请求失败");
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public static class DownloadFileThread extends Thread {
		private String filepath;
		private int startIndex;
		private int endIndex;
		private int threadId;
		private String newFileName;

		public DownloadFileThread(String filepath, int startIndex, int endIndex,int threadId) {
			this.filepath = filepath;
			this.startIndex = startIndex;
			this.endIndex = endIndex;
			this.threadId = threadId;
			this.newFileName = filepath.substring(filepath.lastIndexOf("/") + 1);
		}

		@Override
		public void run() {
			try {
				//为支持断点续传,终止或异常发生时,保存文件下载的最后位置,下次继续下载时读取出来,从上次结束位置开始下载
				//判断是否存在已下载的文件记录,如果存在则开始位置
				File file = new File(threadId + ".txt");
				if(file.exists() && file.length() > 0){
					String tempFileContent = txt2String(file);
					startIndex = Integer.parseInt(tempFileContent);
				}
				
				URL url = new URL(filepath);
				HttpURLConnection conn = (HttpURLConnection) url.openConnection();
				conn.setRequestProperty("Range", "bytes="+startIndex+"-"+endIndex);//请求资源的范围,下载部分文件,需指定开始-结束位置
				conn.setConnectTimeout(5000);
				conn.setRequestMethod("GET");
				int code = conn.getResponseCode();//200是成功,206也是成功,分割一个文件返回206
				InputStream is = conn.getInputStream(); //由于设置了请求的位置,返回的是当前位置对应的输入流
				
				RandomAccessFile raf = new RandomAccessFile(newFileName,"rwd");
				raf.seek(startIndex);
				int len = 0 , total = 0;
				byte[] buffer = new byte[1024];
				while((len = is.read(buffer)) != -1){//没有读到文件末尾则继续写
					raf.write(buffer, 0, len);
					total += len;
					RandomAccessFile info = new RandomAccessFile(threadId + ".txt","rwd");
					info.write((total + startIndex + "").getBytes());//把下载到最后的位置保存写到文件中
					info.close();
				}
				is.close();
				raf.close();
				//System.out.println("线程:"+threadId +"------下载完毕");
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}finally{
				runningThread --;
				//当线程执行完后,表示文件下载完毕,清除临时文件记录
				if(runningThread == 0){
					for(int i=1;i <= threadCount; i++){
						File file = new File(i+".txt");
						if(file.exists()){
							file.delete();
						}
					}
				}
			}
		}
		
		/**
	     * 读取txt文件的内容
	     * @param file 想要读取的文件对象
	     * @return 返回文件内容
	     */
	    public static String txt2String(File file){
	        StringBuilder result = new StringBuilder();
	        try{
	            BufferedReader br = new BufferedReader(new FileReader(file));//构造一个BufferedReader类来读取文件
	            String s = null;
	            while((s = br.readLine())!=null){//使用readLine方法,一次读一行
	                result.append(s);
	            }
	            br.close();    
	        }catch(Exception e){
	            e.printStackTrace();
	        }
	        return result.toString();
	    }
		
	}

}