1,把阿里旺旺传到服务器上
2,分3个线程,分别下载不同位置的文件
3,用3个文件记录每次下载的位置,停止后再次下载时,直接从已下载的位置开始继续下载,当文件下载完成后删除记录的文件
测试成功,下面是实现代码:
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();
}
}
}