java断点下载文件_Java多线程断点下载文件

packagecom.test.download;importjava.io.BufferedReader;importjava.io.File;importjava.io.FileInputStream;importjava.io.InputStream;importjava.io.InputStreamReader;importjava.io.RandomAccessFile;importjava.net.HttpURLConnection;importjava.net.URL;public classMutilDownLoad {//[1]定义下载的路径

private static String path = "http://192.168.33.10:80/test/123456.mp4";private static final int threadCount = 3; //假设开三个线程

private static int runningThread; //代表当前正在运行的线程

public static voidmain(String[] args) {//[一]获取服务器文件的大小 要计算每个线程下载的开始位置和结束位置

try{//(1) 创建一个url对象 参数就是网址

URL url = newURL(path);//(2)获取HttpURLConnection 链接对象

HttpURLConnection conn =(HttpURLConnection) url.openConnection();//(3)设置参数 发送get请求

conn.setRequestMethod("GET"); //默认请求 就是get 要大写//(4)设置链接网络的超时时间

conn.setConnectTimeout(5000);//(5)获取服务器返回的状态码

int code = conn.getResponseCode(); //200 代表获取服务器资源全部成功 206请求部分资源

if (code == 200) {//(6)获取服务器文件的大小

int length =conn.getContentLength();//[6.1]把 线程的数量赋值给正在运行的线程

runningThread =threadCount;

System.out.println("length:" +length);//[二] 创建一个大小和服务器一模一样的文件 目的提前把空间申请出来

RandomAccessFile rafAccessFile = new RandomAccessFile("F:\\"

+ getFilename(path), "rw");

rafAccessFile.setLength(length);//(7)算出每个线程下载的大小

int blockSize = length /threadCount;//[三 计算每个线程下载的开始位置和结束位置 ]

for (int i = 0; i < threadCount; i++) {int startIndex = i * blockSize; //每个线程下载的开始位置

int endIndex = (i + 1) * blockSize - 1;//特殊情况 就是最后一个线程

if (i == threadCount - 1) {//说明是最后一个线程

endIndex = length - 1;

}

System.out.println("线程id:::" + i + "理论下载的位置" + ":"

+ startIndex + "-----" +endIndex);//四 开启线程去服务器下载文件

DownLoadThread downLoadThread = newDownLoadThread(

startIndex, endIndex, i);

downLoadThread.start();

}

}

}catch(Exception e) {

e.printStackTrace();

}

}//定义线程去服务器下载文件

private static class DownLoadThread extendsThread {//通过构造方法把每个线程下载的开始位置和结束位置传递进来

private intstartIndex;private intendIndex;private intthreadId;public DownLoadThread(int startIndex, int endIndex, intthreadId) {this.startIndex =startIndex;this.endIndex =endIndex;this.threadId =threadId;

}

@Overridepublic voidrun() {//四 实现去服务器下载文件的逻辑

try{//(1) 创建一个url对象 参数就是网址

URL url = newURL(path);//(2)获取HttpURLConnection 链接对象

HttpURLConnection conn =(HttpURLConnection) url

.openConnection();//(3)设置参数 发送POST请求

conn.setRequestMethod("POST"); //默认请求 就是get 要大写//(4)设置链接网络的超时时间

conn.setConnectTimeout(5000);//[4.0]如果中间断过 继续上次的位置 继续下载 从文件中读取上次下载的位置

File file= new File("F:\\" + getFilename(path) +threadId+ ".txt");if (file.exists() && file.length() > 0) {

FileInputStream fis= newFileInputStream(file);

BufferedReader bufr= newBufferedReader(newInputStreamReader(fis));

String lastPositionn= bufr.readLine(); //读取出来的内容就是上一次下载的位置

int lastPosition =Integer.parseInt(lastPositionn);//[4.0.1]要改变一下 startIndex 位置

startIndex = lastPosition + 1;

System.out.println("线程id::" + threadId + "真实下载的位置" + ":"

+ startIndex + "-----" +endIndex);

fis.close();//关闭流

}//[4.1]设置一个请求头Range (作用告诉服务器每个线程下载的开始位置和结束位置)

conn.setRequestProperty("Range", "bytes=" + startIndex + "-"

+endIndex);//(5)获取服务器返回的状态码

int code = conn.getResponseCode(); //200 代表获取服务器资源全部成功//206请求部分资源 成功

if (code == 206) {//[6]创建随机读写文件对象

RandomAccessFile raf = new RandomAccessFile("F:\\"

+ getFilename(path), "rw");//[6]每个线程要从自己的位置开始写

raf.seek(startIndex);

InputStream in=conn.getInputStream();//[7]把数据写到文件中

int len = -1;byte[] buffer = new byte[1024 * 1024];//1Mb

int total = 0; //代表当前线程下载的大小

while ((len = in.read(buffer)) != -1) {

raf.write(buffer,0, len);

total+=len;//[8]实现断点续传 就是把当前线程下载的位置 给存起来 下次再下载的时候 就是按照上次下载的位置继续下载//就可以了

int currentThreadPosition = startIndex + total; //比如就存到一个普通的.txt文本中//[9]用来存当前线程下载的位置

RandomAccessFile raff = new RandomAccessFile("F:\\"

+ getFilename(path) + threadId + ".txt", "rwd");

raff.write(String.valueOf(currentThreadPosition)

.getBytes());

raff.close();

}

raf.close();//关闭流 释放资源

System.out.println("线程id:" + threadId + "---下载完毕了");//[10]把.txt文件删除 每个线程具体什么时候下载完毕了 我们不知道

synchronized (DownLoadThread.class) {

runningThread--;if (runningThread == 0) {//说明所有的线程都执行完毕了 就把.txt文件删除

for (int i = 0; i < threadCount; i++) {

File delteFile= new File("F:\\"

+ getFilename(path) + i + ".txt");

delteFile.delete();

}

}

}

}

}catch(Exception e) {

e.printStackTrace();

}

}

}//获取文件的名字

public staticString getFilename(String path) {int start = path.lastIndexOf("/") + 1;returnpath.substring(start);

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值