多线程断点下载

package www.csdn.net;


import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;


/**
 * 多线程下载测试类
 * 
 * @author jianfei
 * 
 */
public class Demo {
// 线程数
private static final int THREADCOUNT = 3;
// 当前开启的线程数
private static int runningThread = THREADCOUNT;


public static void main(String[] args) throws Exception {
// 1.链接服务器 获取要下载的文件长度 创建一个与要现在文件大小相等的临时文件
// String path="http://172.22.64.7:8080/test.avi";
// String path = "http://192.168.56.1:8080/test.avi";
// String path = "http://192.168.56.1:8080/a.rar";
String path = "http://192.168.56.1:8080/a.jpg";
// 创建一个URL
URL url = new URL(path);
// 链接服务器
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5000);
conn.setRequestMethod("GET");
int code = conn.getResponseCode();
if (code == 200) {
// 得到文件长度
int length = conn.getContentLength();
System.out.println("文件长度" + length);
// 在客户端创建一个与服务器端文件一样大小的临时文件
// RandomAccessFile raf = new RandomAccessFile("test.avi", "rwd");
// RandomAccessFile raf = new RandomAccessFile("a.rar", "rwd");
RandomAccessFile raf = new RandomAccessFile("a.jpg", "rwd");
// 指定创建这个文件的长度 也就是大小
raf.setLength(length);
raf.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);
System.out.println("*****************************************");
new DownloadThread(threadId, startIndex, endIndex, path)
.start();
}
} else {
System.out.println("服务器忙");
}
}


/**
* 开启子线程 每一个线程下载对应的文件

* @author jianfei
*/
public static class DownloadThread extends Thread {
private int threadId;
private int startIndex;
private int endIndex;
private String path;


/**

* @param threadId
*            线程id
* @param startIndex
*            线程下载的开始位置
* @param endIndex
*            线程下载结束的位置
* @param path
*            现在文件的路径
*/
public DownloadThread(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() {
try {
// 检查是否存在记录下载长度的文件,如果存在,读取这个文件的数据,实现断点下载
File tempFile = new File(threadId + ".txt");
// System.out.println(tempFile.length()+"??????????/");
// 判断记录文件是否存在,长度是否为零
if (tempFile.exists() && tempFile.length() > 0) {
System.out.println(tempFile.getName() + ">>>>>>>>>>>>>>>>");
// System.out.println("我是断电下载-----");
FileInputStream fis = new FileInputStream(tempFile);
byte[] temp = new byte[1024];
int leng = fis.read(temp);
String downloadLen = new String(temp, 0, leng);
int dowloadlenInt = Integer.parseInt(downloadLen);
// //修改下载位置
startIndex = dowloadlenInt;
fis.close();
}


URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url
.openConnection();


// 设置请求方式
conn.setRequestMethod("GET");
// 请求服务器
conn.setRequestProperty("Range", "bytes=" + startIndex + "-"
+ endIndex);
System.out.println("线程" + threadId + "断点下载" + startIndex
+ "-->" + endIndex);


// 设置超时时间
conn.setReadTimeout(5000);
// 获取服务器的响应码 如果请求全部资源是200 请求部分资源206
int code = conn.getResponseCode();
if (code == 206) {
// System.out.println(code+"------code");
// 服务器端返回的资源
InputStream is = conn.getInputStream();
// RandomAccessFile raf = new RandomAccessFile("test.avi","rwd");
// RandomAccessFile raf = new RandomAccessFile("a.rar","rwd");
RandomAccessFile raf = new RandomAccessFile("a.jpg",
"rwd");
// 随机写文件的时候从哪个位置开始写
raf.seek(startIndex);
int len = 0;
byte[] buffer = new byte[1024];
// 已经下载的长度
int total = 0;
while ((len = is.read(buffer)) != -1) {
// 创建一个文件,用于记录当前下载的长度
RandomAccessFile file = new RandomAccessFile(threadId
+ ".txt", "rwd");
// System.out.println(file.length()+"-----------------???????????#############");
raf.write(buffer, 0, len);
total += len;
System.out.println("线程" + threadId + "total:" + total);
// 记录下载的位置
file.write((total + startIndex + "").getBytes());
file.close();
}
is.close();
raf.close();
System.out.println("线程" + threadId + "下载完毕************");
} else {
System.out.println("服务器忙");
}
// 当线程下载完毕后清除下载记录
// File deleteFile = new File(threadId + ".txt");
// deleteFile.delete();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
} finally {
// 不管是否下载成功,只要线程结束就让赈灾运行的线程数减一
runningThread--;
// 当所有的线程已经执行完毕
if (runningThread == 0) {
for (int i = 1; i <= THREADCOUNT; i++) {
File file = new File(i + ".txt");
file.delete();
}
System.out.println("文件下载完毕,清除所有的下载记录");
}
}
}
}


}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值