多线程IO远程资源下载工具类封装

由于个人最近项目开发有用到从远程服务器下载文件需求,所以在项目中自己封装了一个工具类,该工具类使用多线程方式对一个很大的文件进行分段下载。今天抽点时间做个笔记记录下,如果那里不对请大家多多指教,互相学习嘛。

import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 * 多线程远程资源下载工具类
 * @author zxs
 * @date 2019/08/16
 */
public class DownUtil {

    //定义下载资源路径
    private String path;
    //指定所下载的文件的保存位置
    private String targetFile;
    //定义需要使用多少个线程下载资源
    private int threadNum;

    //定义下载的线程对象
    private DownThread[] threads;
    //定义下载文件的总大小
    private int fileSize;

    public DownUtil(String path, String targetFile, int threadNum) {
        super();
        this.path = path;
        this.targetFile = targetFile;
        this.threadNum = threadNum;
        this.threads = new DownThread[threadNum];
    }

    /**
     * 远程获取资源,计算总文件大小,然后根据多线程分割不同部分下载文件,保存到指定路径目录下
     * @author zxs
     * @date 2019/08/16
     */

    public void download() throws Exception{
        URL url = new URL(path);
        HttpURLConnection conn = (HttpURLConnection)url.openConnection();
        conn.setConnectTimeout(5*1000);
        conn.setRequestMethod("GET");

        conn.setRequestProperty("Accept", "image/gif,image/jpeg,image/pjpeg, "
                + "application/x-shockwave-flash, application/xaml+xml, "
                + "application/vnd.ms-xpsdocument, application/x-ms-xbap, "

                + "applicaiton/x-ms-application, application/vnd.ms-excel, "
                + "application/vnd.ms-powerpoint, application/msword, */*"
                );

        conn.setRequestProperty("Accept-Language", "zh-CN");
        conn.setRequestProperty("Charset", "UTF-8");
        conn.setRequestProperty("Connection", "Keep-Alive");

        //得到文件大小
        fileSize = conn.getContentLength();
        int currentPartSize = fileSize / threadNum + 1;
        RandomAccessFile file = new RandomAccessFile(targetFile,"rw");

        //设置本地文件的大小
        file.setLength(fileSize);
        file.close();

        for (int i = 0; i < threadNum; i++) {
            //计算每个线程下载的开始位置
            int startPos = i * currentPartSize;
            //每个线程使用一个RandomAccessFile进行下载

            RandomAccessFile currentPart = new RandomAccessFile(targetFile,"rw");
            //定位该线程的下载位置
            currentPart.seek(startPos);

            //创建下载线程
            threads[i] = new DownThread(path,startPos,currentPartSize,currentPart);
            //启动下载线程
            threads[i].start();

        }
    }

    /**
     * 获取文件被下载的完成百分比
     * @return
     * @author zxs
     * @date 2019/08/16
     */

    public double getComleteRate() {
        //统计多个线程已经下载的总大小
        int sumSize = 0;
        for (int i = 0; i < threadNum; i++) {
            sumSize += threads[i].length;
        }
        //返回已经完成的百分比
        return sumSize * 1.0 / fileSize;
    }

    public static void main(String[] args) throws Exception {

//        final DownUtil down = new DownUtil("https://images2018.cnblogs.com/blog/1222688/201807/1222688-20180711162915486-1128650164.png", "D:\\pic.png", 4);

        final DownUtil down = new DownUtil("http://10.10.203.54:8889/pic/jsisc-upservice.jar", 
                "D:\\zhuxueshiDownload.jar", 5);

        down.download();
        new Thread(()->{
            while(down.getComleteRate()<1) {
                System.out.println("已经完成:" + down.getComleteRate());
            }

            try {
                Thread.sleep(1000);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }).start();
    }

}

import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
/**
 * 线程下载写入工具类
 * @author zxs
 * @date 2019/08/16
 */
public class DownThread extends Thread{

    private String path;
    //当前线程的下载位置
    private int startPos;
    //定义当前线程负责下载的文件大小
    private int currentPartSize;
    //当前线程需要下载的文件块
    private RandomAccessFile currentPart;
    //定义该线程已下载的字节数
    public int length;

    public DownThread(String path,int startPos, int currentPartSize, RandomAccessFile currentPart) {
        super();
        this.path = path;
        this.startPos = startPos;
        this.currentPartSize = currentPartSize;
        this.currentPart = currentPart;
    }

    @Override
    public void run() {
        try {
            URL url = new URL(path);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setConnectTimeout(5*1000);
            conn.setRequestMethod("GET");

            conn.setRequestProperty("Accept", "image/gif,image/jpeg,image/pjpeg, "
                    + "application/x-shockwave-flash, application/xaml+xml, "
                    + "application/vnd.ms-xpsdocument, application/x-ms-xbap, "

                    + "applicaiton/x-ms-application, application/vnd.ms-excel, "
                    + "application/vnd.ms-powerpoint, application/msword, */*"
                    );

            conn.setRequestProperty("Accept-Language", "zh-CN");
            conn.setRequestProperty("Charset", "UTF-8");
            InputStream inStream = conn.getInputStream();
            inStream.skip(this.startPos);
            byte[] buffer = new byte[2014];
            int hasRead = 0;

            while (length < currentPartSize && (hasRead = inStream.read(buffer))!=-1) {
                currentPart.write(buffer, 0, hasRead);
                //累计该线程下载的总大小
                length += hasRead;
            }

            System.out.println("下载完成:" + length);
            currentPart.close();
            inStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值