java实现多线程文件的断点续传
java文件的多线程断点续传大致原理,供大家参考,具体内容如下
谈到文件断点续传那么就离不开java.io.RandomAcessFile HttpUrlConnection类
大致思路如下:
1、HttpUrlConnection去请求服务器 获得文件的长度con.getContentLength()
2、创建一个空的RandomAcessFile来接收,并且指定刚刚获取的长度setLength
3、开启N个线程 计算每个线程需要下载的长度
4、获取之前先去看看下载的进度保存文件是否存在 如果存在就从文件里获取已经下载的进度
5、开始文件下载
6、临时文件的删除 资源的关闭
下面贴出完整代码
package demo; 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; class MultiDownloaFile { public static final String path = "http://192.168.217.1:8080/androidsimpleserver/HTTP.pdf"; public static final int TOTAL_THREAD_COUNT = 3; public static int runningThreadCount = 0; public static void main(String[] args) { try { long start = System.currentTimeMillis(); URL url = new URL(path); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); int code = conn.getResponseCode(); if (code == 200) { int length = conn.getContentLength(); System.out.println("file length:" + length); //create a null file to save its length RandomAccessFile raf = new RandomAccessFile(getDownloadFileName(path), "rw"); raf.setLength(length); raf.close(); //parse every thread that they need how much room to download int blockSize = length / TOTAL_THREAD_COUNT; System.out.println("every block size:" + blockSize); runningThreadCount = TOTAL_THREAD_COUNT; for (int threadId = 0; threadId < TOTAL_THREAD_COUNT; threadId++) { int startPosition = threadId * blockSize; int endPosition = (threadId + 1) * blockSize - 1; if (threadId == (TOTAL_THREAD_COUNT - 1)) { endPosition = length - 1; } System.out.println("thread::" + threadId + " download range:" + startPosition + "~~" + endPosition); //start thread to download new DownloadThread(threadId, startPosition, endPosition).start(); } } else { System.out.println(" connection error "); } } catch (Exception e) { e.printStackTrace(); } } /** * 从网络路径获取文件名 * * @param path 网络路径 * @return 文件名 */ private static String getDownloadFileName(String path) { return path.substring(path.lastIndexOf("/") + 1); } /** * 下载文件的线程 */ private static class DownloadThread extends Thread { /** * 线程id */ private int threadId; /** * 当前线程下载的起始位置 */ private int startPosition; /** * 当前线程下载的终止位置 */ private int endPosition; public DownloadThread(int threadId, int startPosition, int endPosition) { this.threadId = threadId; this.startPosition = startPosition; this.endPosition = endPosition; } @Override public void run() { System.out.println("thread:" + threadId + " begin working"); // lest thread download it's self range data try { File finfo = new File(TOTAL_THREAD_COUNT + getDownloadFileName(path) + threadId + ".txt"); // 断点续传 if (finfo.exists() && finfo.length() > 0) { System.out.println(" 断点续传开始"); FileInputStream fis = new FileInputStream(finfo); BufferedReader br = new BufferedReader(new InputStreamReader(fis)); String lastPosition = br.readLine(); // This thread download data before times; int intLastPosition = Integer.parseInt(lastPosition); startPosition = intLastPosition; fis.close(); } URL url = new URL(path); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); System.out.println("begin and end:" + threadId + " range of download: " + startPosition + "~~" + endPosition); conn.setRequestProperty("Range", "bytes=" + startPosition + "-" + endPosition); // Download Resource from server int code = conn.getResponseCode(); if (code == 206) { InputStream is = conn.getInputStream(); // RandomAccessFile raf = new RandomAccessFile(getDownloadFileName(path), "rw"); RandomAccessFile raf = new RandomAccessFile(getDownloadFileName(path), "rw"); // vary important, position of begin to write raf.seek(startPosition); byte[] buffer = new byte[1024 * 100]; int len = -1; int total = 0; // downloaded data of current thread in this times; while ((len = is.read(buffer)) != -1) { raf.write(buffer, 0, len); // record position of current thread to downloading total += len; RandomAccessFile inforaf = new RandomAccessFile(TOTAL_THREAD_COUNT + getDownloadFileName(path) + threadId + ".txt", "rwd"); // save position of current thread inforaf.write(String.valueOf(startPosition + total).getBytes()); inforaf.close(); } is.close(); raf.close(); System.out.println("thread:" + threadId + " download complete..."); } else { System.out.println("request download failed."); } } catch (Exception e) { e.printStackTrace(); } finally { synchronized (MultiDownloaFile.class) { runningThreadCount--; if (runningThreadCount <= 0) { System.out.println(" all multi thread download complete. success!!!"); for (int i = 0; i < TOTAL_THREAD_COUNT; i++) { File finfo = new File(TOTAL_THREAD_COUNT + getDownloadFileName(path) + i + ".txt"); System.out.println(finfo.delete()); } } } } } } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。
相关文章
IDEA Ui设计器JFormDesigner 永久激活插件+注册机(亲测一直在用)
这篇文章主要介绍了IDEA Ui设计器JFormDesigner 永久激活----插件+注册机 自己一直在用的版本和注册机,非常不错,本文通过图文并茂的形式给大家介绍的非常详细,需要的朋友可以参考下2022-08-08Spring Boot多数据源事务@DSTransactional的使用详解
本文主要介绍了Spring Boot多数据源事务@DSTransactional的使用详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧2023-06-06
最新评论