多线程下载之断点续传采用随机文件读取流,HttpConnection实现

来源:互联网 发布:东安格利亚大学知乎 编辑:程序博客网 时间:2024/06/06 20:24

/**
*
*/
package com.l000phone.multithreaddown.advanced;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

/**
* Description: 多线程从服器端下载资源演示(网络出现异常,需要进行断点续传)

* Copyright (c) , 2016, Jansonxu

* This program is protected by copyright laws.

* Program Name:Download.java

* Date: 2016-2-16
*
* @author 李阳
* @version : 1.0
*/
public class AdvancedDownload {

/** * @param args */public static void main(String[] args) {    // 1、在客户端获得服务器资源的长度,根据此长度在客户端创建一个临时文件    try {        URL url = new URL(                "http://localhost:8080/ServerSide/file/VNC-5.1.1-Windows.exe");        HttpURLConnection conn = (HttpURLConnection) url.openConnection();        if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {            int resLen = conn.getContentLength();            System.out.println("要下载资源的长度是:" + resLen);            RandomAccessFile raf = new RandomAccessFile(new File(                    "download/VNC-5.1.1-Windows.exe"), "rwd");// 创建临时文件            raf.setLength(resLen);            raf.close();// 关闭资源            // 2、获得每个线程下载资源的开始和结束位置            // 3、开启多个线程从服务其下载资源,直到所有的线程执行完毕            int blockSize = resLen / 3;// 每个线程平均下载的长度            AdvancedDownload outer = new AdvancedDownload();// 外部类对象            // 创建文件对象(记录各个子线程下载的最终结果)            File threadDownadStatusFile = new File(                    "download/finalStauts.txt");            if (!threadDownadStatusFile.exists()) {                threadDownadStatusFile.createNewFile();            }            for (int threadId = 1; threadId <= 3; threadId++) {                // ①开始位置                int startPos = (threadId - 1) * blockSize;                // ②结束位置                int endPos = threadId * blockSize - 1;                if (threadId == 3) {                    endPos = resLen - 1;                }                // ③启动子线程下载                outer.new DownloadSonThread(startPos, endPos, url,                        threadId, threadDownadStatusFile).start();            }        }    } catch (MalformedURLException e) {        e.printStackTrace();    } catch (IOException e) {        e.printStackTrace();    }}/** * 资源下载子线程 */private class DownloadSonThread extends Thread {    private int startPos;    private int endPos;    private URL url;    private int threadId;    private File threadDownadStatusFile;    public DownloadSonThread(int startPos, int endPos, URL url,            int threadId, File threadDownadStatusFile) {        super();        this.startPos = startPos;        this.endPos = endPos;        this.url = url;        this.threadId = threadId;        this.threadDownadStatusFile = threadDownadStatusFile;    }    @Override    public void run() {        // ①获得连接实例        try {            HttpURLConnection conn = (HttpURLConnection) url                    .openConnection();            // 读取线程字节数记录文件中的数据,作为开始线程下载的开始位置            File file = new File("download/" + threadId + ".txt");            if (file.exists()) {                BufferedReader br = new BufferedReader(new FileReader(file));                String startPosRecord = br.readLine();                startPos = Integer.parseInt(startPosRecord);                br.close();            }            // ②设置连接的属性为下载部分资源            conn.setRequestProperty("Range", "bytes=" + startPos + "-"                    + endPos);            System.out.println("来自服务器端的状态码:" + conn.getResponseCode());            // ③从服务器获取资源,填充本地客户端的临时文件            if (conn.getResponseCode() == 206) {// 206:服务器端的资源是属于分段下载的、200:服务端所有的资源都发送给了客户端                // a)获得网络字节输入流                InputStream is = conn.getInputStream();                byte[] b = new byte[1024];                int len = 0;                // b)将流中的数据写入到本地临时文件中                RandomAccessFile raf = new RandomAccessFile(new File(                        "download/VNC-5.1.1-Windows.exe"), "rwd");// 向临时文件中写入数据                raf.seek(startPos);                int totalBytes = startPos;// 当前线程已经下载的字节数                while ((len = is.read(b)) != -1) {                    // seek移动指针偏移量,写入数据                    raf.write(b, 0, len);                    totalBytes += len;// 累加目前已经下载的字节数                    RandomAccessFile nowRecordLenFile = new RandomAccessFile(                            new File("download/" + threadId + ".txt"),                            "rwd");                    nowRecordLenFile.write((totalBytes + "").getBytes());                    nowRecordLenFile.close();                }                raf.close();                System.out.println("线程" + threadId + "下载资源完毕....");                FileWriter fw = new FileWriter(threadDownadStatusFile, true);                fw.write(threadId + "over");                fw.close();            }        } catch (IOException e) {            e.printStackTrace();        } finally {            // 读取文件中的内容,若发现内容匹配:            // 内容.contains("thread1over") 并且 内容.contains("thread2over") 并且            // 内容.contains("thread3over")            // 就删除各个临时文件            BufferedReader br = null;            try {                br = new BufferedReader(new FileReader(                        threadDownadStatusFile));                String finalResultInfo = br.readLine();                if (finalResultInfo.contains("1over")                        && finalResultInfo.contains("2over")                        && finalResultInfo.contains("3over")) {                    for (int threadId = 1; threadId <= 3; threadId++) {                        new File("download/" + threadId + ".txt").delete();                    }                    br.close();                    new File("download/finalStauts.txt").delete();                    System.out.println("恭喜!所有临时文件都已经删除掉了哦!...");                }            } catch (FileNotFoundException e) {                e.printStackTrace();            } catch (IOException e) {                e.printStackTrace();            }        }    }}

}

2 0
原创粉丝点击