java多线程下载服务器资源文件-------(demo)支持断点下载

来源:互联网 发布:java实现文件上传下载 编辑:程序博客网 时间:2024/05/22 08:22

import java.io.BufferedReader;import java.io.File;import java.io.FileInputStream;import java.io.InputStream;import java.io.InputStreamReader;import java.io.RandomAccessFile;import java.net.HttpURLConnection;import java.net.URL;public class Main {// 设置线程的数量为3private final static int THRED_COUNT = 3;final static String path = "http://188.188.7.85/kugou.exe";public static void main(String[] args) {System.out.println(getFilename());// 创建三个线程进行多线程的下载资源文件try {URL url = new URL(path);// 1.获取文件资源的连接HttpURLConnection conn = (HttpURLConnection) url.openConnection();// 2.获取服务器资源文件的大小int length = conn.getContentLength();//3.在本地生成与之一样的文件,使用随机流RandomAccessFile raf = new RandomAccessFile(getFilename(), "rw");//设置文件的长度raf.setLength(length);//4.开始划分每一个线程从什么位置下载到什么位置int blockSize = length  / THRED_COUNT;//5.开启3个线程进行下载for (int threadId = 0; threadId < THRED_COUNT; threadId++) {//每个线程的下载开始位置int startIndex = threadId*blockSize;//线程下载的结束位置int endIndex = (threadId + 1 )*blockSize -1;//如果是最后一个线程,让这个线程执行后面剩余的文字资源if(threadId == THRED_COUNT){endIndex = length - 1;}//开始线程去下载,并传递进去每一个线程下载的起始位置new Downloader(threadId,startIndex,endIndex).start();}} catch (Exception e) {e.printStackTrace();}}//获取路径中的文件名private static String getFilename(){return path.substring(path.lastIndexOf("/")+1);}//下载的线程static class Downloader extends Thread{private int startIndex;private int endIndex;private int threadId;private int currentPosition;public Downloader(int threadId,int startIndex,int endIndex) {this.startIndex = startIndex;this.endIndex = endIndex;this.threadId = threadId;currentPosition = startIndex;System.out.println("线程"+threadId+"-下载的位置从:" + startIndex+" ---"+endIndex);}@Overridepublic void run() {try{//先找到之前记录好的位置信息File  file = new File(threadId+".position");//判断以前曾经下载过文件,这个时候必须读取里里面的位置信息  //(断点下载的方式:就是记录每次下载之后的位置,并实时保存到硬盘中,所以使用到了随机流进行实时写出断点下载的位置文件信息)if(file.exists() && file.length()>0){FileInputStream fis = new FileInputStream(file);BufferedReader bReader = new BufferedReader(new InputStreamReader(fis));//读取线程曾经下载到的位置currentPosition = Integer.parseInt(bReader.readLine());System.out.println("以前有下载过文件--"+threadId +"--从"+currentPosition+"开始下载");bReader.close();fis.close();}else{System.out.println("以前没有下载过文件,从头开始下载------");}URL url = new URL(path);HttpURLConnection conn =  (HttpURLConnection) url.openConnection();//conn.getInputStream()//获取这个资源对应的所有输入流//为了实现每一线程下载的东西都是固有的位置,所以必须告诉服务器,每一个线程从什么位置开始下载//设置线程下载资源的位置conn.setRequestProperty("Range", "bytes:"+currentPosition+"-"+endIndex);//获取线程访问返回的状态码    线程下载返回的是206int code = conn.getResponseCode();if(206 == code){InputStream in = conn.getInputStream();//写文件的时候要注意,因为已经规定了每一个线程从什么位置开始下载,所以//写数据的时候必须从指定位置开始写入RandomAccessFile raf = new RandomAccessFile(getFilename(), "rw");raf.seek(currentPosition);byte[] buffer = new byte[1024];int len = 0;while((len = in.read(buffer)) != -1){raf.write(buffer,0,len);//这几必须写在上面这句语句后面,不然会数据混乱问题出现问题currentPosition  += len;//必须使用随机流进行读写现在下载位置的配置信息,不然会出现各种问题,(主要是硬盘的缓存问题)RandomAccessFile fos= new RandomAccessFile(threadId+".position", "rwd");fos.write((currentPosition+"").getBytes());fos.close();}System.out.println("线程"+threadId+"--已经下载结束了。。");//下载完成之后,要删除(断点下载的配置文件.position)//如果存在断点配置.position文件,将其删除file.delete();raf.close();in.close();}}catch (Exception e) {e.printStackTrace();}}}}

一.注意:多线程下载资源文件是为了提高效率(比如:迅雷下载)

断点下载的原理:每次读取到的文件都将其的位置写入配置文件中


下面是一个Demo:





0 0
原创粉丝点击