Java多线程下载,断点续传

原创 2016年12月17日 11:58:49

转载请标明出处:http://blog.csdn.net/wu_wxc/article/details/53706114
本文出自【吴孝城的CSDN博客】

在Java中实现断点续传和多线程下载

package cn.wuxiaocheng;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
public class Download {
    private static final String PATH = "http://169.254.217.86:8080/Down/test.exe";
    // 假设开了三个线程
    private static final int THREADCOUNT = 3;
    // 当前正在运行的线程
    private static int RUNTHREAD;
    public static void main(String[] args) {
        try {
            HttpURLConnection conn = (HttpURLConnection) new URL(PATH).openConnection();
            conn.setRequestMethod("GET");
            conn.setConnectTimeout(5000);
            // 200代表获取服务器资源全部成功,206代表请求部分资源
            int code = conn.getResponseCode();
            if (code == 200) {
                // 获取要下载的文件大小
                int length = conn.getContentLength();
                // 把线程的数据赋值给正在运行的线程
                RUNTHREAD = THREADCOUNT;
                System.out.println("要下载的文件大小为" + length + "字节");
                /**
                 * 创建一个和要下载的文件一样大小的文件,提前把空间申请出来 一般可用来计算空间是否充足,也可不定
                 * RandomAccessFile 创建可随机访问文件流 rw 参数是打开以便读取和写入,如果文件不存在,则尝试创建
                 */
                RandomAccessFile raf = new RandomAccessFile(getFileName(PATH), "rw");
                // 存入该文件大小
                raf.setLength(length);
                // 计算每个线程下载的大小
                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;
                    }
                    // 开始线程去服务器下载东西
                    DownloadThread downloadThread = new DownloadThread(startIndex, endIndex, i);
                    downloadThread.start();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    // 定义线程去服务器下载文件
    private static class DownloadThread extends Thread {
        private int startIndex;
        private int endIndex;
        private int threadID;
        // 通过构造方法将每个线程开始和结束位置传递过来
        public DownloadThread(int startIndex, int endIndex, int threadID) {
            this.startIndex = startIndex;
            this.endIndex = endIndex;
            this.threadID = threadID;
        }
        @Override
        public void run() {
            try {
                HttpURLConnection conn = (HttpURLConnection) new URL(PATH).openConnection();
                conn.setRequestMethod("GET");
                conn.setConnectTimeout(5000);
                // 如果上次有断过,从文件中读取上次下载的位置
                File file = new File(getFileName(PATH) + threadID + ".txt");
                if (file.exists() && file.length() > 0) {
                    FileInputStream fios = new FileInputStream(file);
                    BufferedReader buffer = new BufferedReader(new InputStreamReader(fios));
                    String lastPositionn = buffer.readLine();
                    int lastPosition = Integer.parseInt(lastPositionn);
                    // 改变startIndex的值
                    startIndex = lastPosition;
                    System.out.println(threadID + "线程下载的位置:" + startIndex);
                    fios.close();
                }
                // 设置一个请求头,告诉服务器每个线程下载的开始和结束位置
                conn.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex);
                // 200代表获取服务器资源全部成功,206代表请求部分资源
                int code = conn.getResponseCode();
                if (code == 206) {
                    /**
                     * 创建一个和要下载的文件一样大小的文件,提前把空间申请出来 一般可用来计算空间是否充足,也可不定
                     * RandomAccessFile 创建可随机访问文件流 rw 参数是打开以便读取和写入,如果文件不存在,则尝试创建
                     */
                    RandomAccessFile raf = new RandomAccessFile(getFileName(PATH), "rw");
                    raf.seek(startIndex);
                    // 获得要下载的文件
                    InputStream in = conn.getInputStream();
                    // 将数据写入到文件中
                    int len = 0;
                    byte[] buffer = new byte[1024 * 1024];
                    // 定义一个total,记录当前线程下载的位置
                    int total = 0;
                    while ((len = in.read(buffer)) != -1) {
                        raf.write(buffer, 0, len);
                        // 断点续传,下次下载的时候就从上次的位置开始
                        total += len;
                        int currentThreadPosition = startIndex + total;
                        // 用txt文件存储下载位置
                        RandomAccessFile raff = new RandomAccessFile(getFileName(PATH) + threadID + ".txt", "rwd");
                        raff.write(String.valueOf(currentThreadPosition).getBytes());
                        raff.close();
                    }
                    // 关闭流,释放资源
                    raf.close();
                    System.out.println("线程" + threadID + "下载完成了");
                    synchronized (DownloadThread.class) {
                        RUNTHREAD--;
                        if (RUNTHREAD == 0) {
                            // 说明所有的线程都执行完毕,把.txt文件删除
                            for (int i = 0; i < THREADCOUNT; i++) {
                                File deleteFile = new File(getFileName(PATH) + i + ".txt");
                                deleteFile.delete();
                            }
                        }
                    }
                }
            } catch (MalformedURLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
    // 获取下载的文件的名字,http://169.254.217.86:8080/Down/test.exe
    private static String getFileName(String path) {
        int start = path.lastIndexOf("/") + 1;
        return path.substring(start);
    }
}
版权声明:本文为博主原创文章,未经博主允许不得转载。

Java代码实现多线程下载和断点续传

- 多线程下载原理 客户端要下载一个文件, 首先请求服务器,服务器将这个文件传送给客户端,客户端保存到本地, 完成了一个下载的过程. 多线程下载的思想是客户端开启多个线程同时下载,每个线程只负责下载文...
  • qq_32101859
  • qq_32101859
  • 2016年11月15日 21:10
  • 4626

java实现FTP多线程断点续传,上传下载!

java实现FTP多线程断点续传,上传下载! 2015-12-26 06:45 357人阅读 评论(0) 收藏 举报  分类: 建站工具 服务器(1)  添...
  • gaoqiao1988
  • gaoqiao1988
  • 2016年10月24日 14:01
  • 2816

在Java中使用多线程结合断点续传实现一个简单的文件下载器

这篇博客介绍在android中使用多线程和断点续传实现一个简单的文件下载器 第一步:启动Tomcat服务器,将需要下载的文件部署到Tomcat服务器上 第二步:使用eclipse创建一个J...
  • u010105970
  • u010105970
  • 2016年04月23日 13:25
  • 1749

java 断点续传 多线程下载 线程池下载

  • 2017年06月27日 14:00
  • 12KB
  • 下载

java实现多线程断点续传下载

  • 2013年08月27日 23:29
  • 6KB
  • 下载

Java实现多线程下载和断点续传

  • 2010年04月02日 22:20
  • 11KB
  • 下载

java编写的下载器,支持多线程断点续传&amp;任务管理

  • 2015年07月10日 15:09
  • 88KB
  • 下载

JAVA多线程断点续传下载

JAVA多线程断点续传下载           多个线程同时去下载一个资源,肯定比一个线程去下载一个资源速度快的多,所以现在我们要实现一下多个线程去下载一个资源,而断点下载的意思是,如果上一次因为...
  • u013263323
  • u013263323
  • 2015年06月15日 15:53
  • 465

Androidx学习笔记(43)--- 带断点续传的多线程下载(java项目)

带断点续传的多线程下载 定义一个int变量记录每条线程下载的数据总长度,然后加上该线程的下载开始位置,得到的结果就是下次下载时,该线程的开始位置,把得到的结果存入缓存文件 //用来记录...
  • oBuYiSeng
  • oBuYiSeng
  • 2016年02月02日 17:29
  • 259

Android学习记录(5)—在java中学习多线程下载之断点续传②

在上一节中我们学习了在java中学习多线程下载的基本原理和基本用法,我们并没有讲多线程的断点续传,那么这一节我们就接着上一节来讲断点续传,断点续传的重要性不言而喻,可以不用重复下载,也可以节省时间,实...
  • loongggdroid
  • loongggdroid
  • 2014年01月04日 12:03
  • 2146
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Java多线程下载,断点续传
举报原因:
原因补充:

(最多只允许输入30个字)