所谓断点下载,是指因异常原因(如:断电)导致下载失去连接后,重新下载会继续进度,而不会从头开始。
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URISyntaxException;
import java.net.URL;
import java.text.DecimalFormat;
/**
* 多线程断点下载工具
* 1.通过提供的网络文件地址,下载该文件
* 2.使用多个线程同时下载,并且实时更新下载进度(0%~100%)
* 3.实现断点功能
*/
public class ThreadsNetDownload extends Thread {
private File targetFile; // 目标文件
private URL url; // 打开链接
private long length; // 下载资源的大小
private static long proccess; // 下载进程
private int count;
public ThreadsNetDownload(File targetFile, URL url, long length) {
super();
this.targetFile = targetFile;
this.url = url;
this.length = length;
}
@Override
public void run() {
if (this.getName().equals("下载线程1")) {
Download(0, length / 4);
} else if (this.getName().equals("下载线程2")) {
Download(length / 4, length / 2);
} else if (this.getName().equals("下载线程3")) {
Download(length / 2, length * 3 / 4);
} else {
Download(length * 3 / 4, length);
}
if(proccess/length == 1){
System.out.println("当前下载进度:100%");
System.out.println("拷贝完成!!");
}
}
/**
* 下载文件
*/
private void Download(long start, long end) {
InputStream is;
BufferedInputStream bis = null;
RandomAccessFile writer = null;
try {
// 打开一个URL链接
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
// 设置请求方法(get请求)
conn.setRequestMethod("GET");
// 获取响应的状态码
int code = conn.getResponseCode();
// 判断是否响应成功
if (code == HttpURLConnection.HTTP_OK) {
is = conn.getInputStream();
bis = new BufferedInputStream(is);
} else {
System.out.println("资源无响应。");
}
writer = new RandomAccessFile(targetFile, "rw");
// start += getRecord();
bis.skip(start);
writer.seek(start);
byte[] b = new byte[1024];
int len = 0;
while ((len = bis.read(b)) != -1 && count <= end - start) {
count += len;
//记录当前文件下载到的位置
setRecord(count);
// System.out.println(this.getName()+"记录进度:" + getRecord()/1024);
//下载进度
proccess += len;
if(proccess/length < 1){
System.out.println("当前下载进度:" + new DecimalFormat("##.##%").format((double)proccess/length));
}
writer.write(b, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally{
try {
if (writer != null)
writer.close();
if (bis != null)
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 从文件中读取进度
* @return
*/
private long getRecord() {
long rec = 0L;
File file = new File(targetFile.getParent(),this.getName()+".txt");
RandomAccessFile reader = null;
try {
reader = new RandomAccessFile(file,"r");
rec = reader.readLong();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally{
if(reader != null)
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return rec;
}
/**
* 记录当前进度到文件中
* @param count
*/
private void setRecord(long count) {
File file = new File(targetFile.getParent(),this.getName()+".txt");
RandomAccessFile writer = null;
try {
writer = new RandomAccessFile(file,"rw");
writer.writeLong(count);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally{
if(writer != null)
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) throws IOException,
URISyntaxException {
String s = "http://192.168.46.254:8888/easyBuy/images/plmm.jpg";
// 根据字符串构建一个URL对象
URL url = new URL(s);
// 打开一个URL链接
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
// 设置请求方法(get请求)
conn.setRequestMethod("GET");
long len = conn.getContentLength();
// 准备目标文件
File f = new File(
"C:\\Documents and Settings\\Administrator\\桌面\\test",
s.substring(s.lastIndexOf("/")));
ThreadsNetDownload tnd1 = new ThreadsNetDownload(f, url, len);
ThreadsNetDownload tnd2 = new ThreadsNetDownload(f, url, len);
ThreadsNetDownload tnd3 = new ThreadsNetDownload(f, url, len);
ThreadsNetDownload tnd4 = new ThreadsNetDownload(f, url, len);
tnd1.start();
tnd1.setName("下载线程1");
tnd2.start();
tnd2.setName("下载线程2");
tnd3.start();
tnd3.setName("下载线程3");
tnd4.start();
tnd4.setName("下载线程4");
}
}
那么有人就问了,“哎,博主这篇博客的对我们的作用何在呢?”
“有的,一切为了java的学习...”