Java多线程断点续传下载

来源:互联网 发布:windows放大镜快捷键 编辑:程序博客网 时间:2024/05/22 03:15
package com.example.threadpool;import java.io.File;import java.io.FileInputStream;import java.io.InputStream;import java.io.RandomAccessFile;import java.net.HttpURLConnection;import java.net.URL;/** * Created by on 2017/11/23. */public class DownloadTest2 {    private static String path = "http://120.27.23.105/version/baidu.apk";    private static int threadCount = 20;    private static int activeThread;    public static void main(String[] arg0){        try {            //构造请求路径            URL url = new URL(path);            //打开连接地址            HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();            //设置请求时间            httpURLConnection.setConnectTimeout(5000);            //设置请求方式            httpURLConnection.setRequestMethod("GET");            //获取请求码            int code = httpURLConnection.getResponseCode();            if(code == 200){                //请求成功                //获取请求数据的长度                int contentLength = httpURLConnection.getContentLength();                //在客户端创建一个大小相同的临时文件                RandomAccessFile randomAccessFile = new RandomAccessFile("baidu.apk","rwd");                //指定临时文件的长度(和下载长度相同)                randomAccessFile.setLength(contentLength);                //关闭流                randomAccessFile.close();                //求出诶条线城需要下载的长度                int blockSize = contentLength / threadCount;                //循环开启线程                for (int i = 1; i < threadCount; i++) {                    //计算当前线程下载的开始位置                    int startIndex = blockSize * (i - 1);                    //计算当前线程下载的结束位置                    int endIndex = blockSize * i - 1;                    //确定是最后一个线程(最后一个线程需要特殊处理)                    if(i == threadCount){                        //i == threadCount说明是最后一个线程                        //为最后一个线程赋值最大长度                        endIndex = contentLength;                    }                    //显示下载数据的区间                    System.out.println("线程【" + i + "】开始下载:" + startIndex + "---->" + endIndex);                    //开启线程进行下载                   new DownloadThread(path,i,startIndex,endIndex).start();                    activeThread ++;                    System.out.println("当前活动的线程数:" + activeThread);                }            }else{                System.out.println("服务器异常,下载失败!");            }        } catch (Exception e) {            e.printStackTrace();        }    }    //内部类分配线程    public static class DownloadThread extends Thread{        //路径        private String path;        private int threadId;        private int startIndex;        private int endIndex;        //有参构造        public DownloadThread(String path, int threadId, int startIndex, int endIndex) {            this.path = path;            this.threadId = threadId;            this.startIndex = startIndex;            this.endIndex = endIndex;        }        @Override        public void run() {                try {                    //构造URL地址                    File file = new File(threadId+".txt");                    //检查记录是否存在,如果存在读取数据                    if(file.exists()){                        //文件流                    FileInputStream fileInputStream = new FileInputStream(file);                    //读取长度                        byte[] temp = new byte[1024];                        int read = fileInputStream.read(temp);                        //读取到已经下载的位置                        int downloadNewindex = Integer.parseInt(new String(temp, 0, read));                        //重新设置开始下载的开始位置                        startIndex = downloadNewindex;                        fileInputStream.close();                        //显示真实下载数据的区间                        System.out.println("线程【" + threadId + "】真实开始下载数据区间:" + startIndex + "---->" + endIndex);                    }                    //设置读取                    URL url = new URL(path);                    //数据请求                    HttpURLConnection connection = (HttpURLConnection) url.openConnection();                    //设置读取时间                    connection.setConnectTimeout(5000);                    //设置读取方式                    connection.setRequestMethod("GET");                    //设置请求头,请求属性和请求资源部分                    connection.setRequestProperty("Range","bytes="+startIndex+"-"+endIndex);                    //请求码                    int code = connection.getResponseCode();                    //因为加了请求头,请求成功返回206                    if(code == 206){                        InputStream inputStream = connection.getInputStream();                        //构建随机的访问文件                        RandomAccessFile randomAccessFile = new RandomAccessFile("baidu.apk","rwd");                        //社会组诶一段随机开始的位置                        randomAccessFile.seek(startIndex);                        //开始写文件                        int len = 0;                        byte[] buffer = new byte[1024];                        //该线程已下载的数据长度                        int total = 0;                        //读取写入                        while ((len = inputStream.read(buffer)) != -1){                            //记录当前线程已下载数据的长度                            RandomAccessFile accessFile = new RandomAccessFile(threadId+".txt","rwd");                            accessFile.write(buffer,0,len);                            //更新线程已下载的长度                            total += len;                            System.out.println("线程【" + threadId + "】已下载数据:" + (total + startIndex));                            //将已下载数据的位置记录写入到文件                            accessFile.write((startIndex+total+"").getBytes());                            accessFile.close();                        }                        inputStream.close();                        randomAccessFile.close();                        //提示下载完毕                        System.out.println("线程【" + threadId + "】下载完毕");                    }                } catch (Exception e) {                    e.printStackTrace();                    System.out.println("线程【" + threadId + "】下载出现异常!!");                }finally {                    //关闭线程                    activeThread--;                    if(activeThread == 0){                        for (int i = 0; i < threadCount; i++) {                            File file = new File(i+".txt");                            //清理文件                            file.delete();                        }                        System.out.println("下载完毕,已清除全部临时文件");                    }                }        }    }} 




原创粉丝点击