多线程断点下载----java
来源:互联网 发布:软件恢复大师 编辑:程序博客网 时间:2024/05/17 23:03
// 多线程断点下载客户端package com.download;import java.io.File;import java.io.FileInputStream;import java.io.InputStream;import java.io.RandomAccessFile;import java.net.HttpURLConnection;import java.net.URL;import java.net.URLConnection;/** * 多线程断点下载 * 说明: * 每一个线程下载的位置计算方式: * 开始位置: (线程id - 1) * 每一块大小 * 结束位置: (线程id * 每一块大小) - 1 * -----注意有时候不一定能够整除,所以最后一个线程的位置应该是文件的末尾 * 步骤: * 1. 本地创建一个大小跟服务器文件相同的临时文件 * 2. 计算分配几个线程去下载服务器上的资源,知道每个线程下载文件的位置 * 3. 开启三个线程,每一个线程下载对应位置的数据 * 4. 如果所有的线程都把自己的数据下载完毕后,服务器上的资源都被下载到本地了 * * 断点下载: * 1. 使用文件记录每一个线程的下载长度 * 2. 每一个下载开始之前,读取文件;如果文件存在并且长度大于0,则取出长度 * 3. 将每一个线程的起始位置 + 已下载的长度 * 4. 所有的线程下载完毕后,删除保存下载长度的文件 * */public class Download { private static String urlPath = "http://10.0.0.0:8080/aaa/bbb/ccc.txt"; private static String localPath = "E://test//1111"; private static String tmpFilePath = localPath + File.separator + "tmp"; private static int threadCount = 3; private static int runningThread = 3; public static void main(String[] args) throws Exception{ // 1. 连接服务器,获取一个文件,获取文件的长度,在本地创建一个跟服务器一样大小的临时文件 URL url = new URL(urlPath); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setConnectTimeout(5000); conn.setRequestMethod("GET"); int code = conn.getResponseCode(); if (code == 200) { // 服务端返回数据的长度,实际上就是文件的长度 int length = conn.getContentLength(); System.out.println("文件总长度:" + length); if (length == -1) { System.out.println("返回数据中不存在文件的长度类型,无法下载"); return ; } // 在客户端本地创建一个大小跟服务器端一样大小的临时文件 RandomAccessFile raf = new RandomAccessFile(tmpFilePath, "rwd"); // 指定创建的文件长度 raf.setLength(length); raf.close(); // 假设是3个线程去下载资源,平均每一个线程下载的文件块长度 int blockSize = length / threadCount; for (int threadId = 1; threadId <= threadCount; threadId++) { // 第一个线程下载的开始位置 int startIndex = (threadId - 1) * blockSize; int endIndex = threadId * blockSize - 1; if (threadId == threadCount) { // 最后一个线程下载的长度要稍微长一点 endIndex = length; } System.out.println("线程:" + threadId + " 下载:------" + startIndex + "----->" + endIndex); new DownloadThread(urlPath, threadId, startIndex, endIndex).start(); } } else { System.out.println("服务器错误"); } } public static class DownloadThread extends Thread { private String urlPath; private int threadId; private int startIndex; private int endIndex; public DownloadThread(String urlPath, int threadId, int startIndex, int endIndex) { super(); this.urlPath = urlPath; this.threadId = threadId; this.startIndex = startIndex; this.endIndex = endIndex; } @Override public void run() { try { // 检查是否存在记录下载长度的文件,如果存在读取这个文件 File tmp_file = new File(localPath + File.separator + threadId + ".txt"); if (tmp_file.exists() && tmp_file.length() > 0) { FileInputStream fis = new FileInputStream(tmp_file); byte[] temp = new byte[1024]; int len = fis.read(temp); String downloadLen = new String(temp, 0, len); int downloadInt = Integer.valueOf(downloadLen); // 修改下载的真实的开始位置 startIndex = downloadInt; System.out.println("线程:" + threadId + "真实的下载位置:" + startIndex + "---->" + endIndex); fis.close(); } URL url = new URL(urlPath); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setConnectTimeout(5000); conn.setRequestMethod("GET"); // 重要: 请求服务器下载部分文件, 指定文件的位置 conn.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex); // 从服务器请求全部资源 返回 200 OK 如果从服务器请求部分资源 返回 206 OK int code = conn.getResponseCode(); System.out.println("code: " + code); InputStream is = conn.getInputStream(); // 已经设置了请求的位置,返回的是当前位置对应的文件的输入流 RandomAccessFile raf = new RandomAccessFile(tmpFilePath, "rwd"); // 随机写文件的时候从哪个位置开始写 raf.seek(startIndex); // 定位文件 int len = 0; byte[] buffer = new byte[1024]; int total = 0; // 已经下载的数据长度 while ((len = is.read(buffer)) != -1) { RandomAccessFile file = new RandomAccessFile(localPath + File.separator + threadId + ".txt", "rwd"); raf.write(buffer, 0, len); total += len; file.write(("" + (total + startIndex)).getBytes()); file.close(); } is.close(); raf.close(); System.out.println("线程:" + threadId + "下载完毕"); } catch (Exception e) { e.printStackTrace(); } finally { runningThread--; if (runningThread == 0) { // 所有的线程执行完毕 for (int i = 1; i <= threadCount; i++) { File file = new File(localPath + File.separator + i + ".txt"); file.delete(); } System.out.println("文件全部下载完毕!"); } } } }}// 服务端代码package com.download;import java.io.BufferedInputStream;import java.io.File;import java.io.FileInputStream;import javax.servlet.ServletOutputStream;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.springframework.context.annotation.Scope;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestParam;@Controller@Scope(value="request")@RequestMapping("/user")public class UserController { public void download(@RequestParam("fileName") String fileName, HttpServletRequest request, HttpServletResponse response) throws Exception{ if (fileName != null) { String realPath = request.getServletContext().getRealPath("/"); File file = new File(realPath); if (file.exists()) { response.setContentType("application/force-download"); // 设置强制下载不打开 response.addHeader("Content-Disposition", "attachment;fileName=" + fileName); // 设置文件名 response.setContentLength((int) file.length()); byte[] buffer = new byte[1024]; FileInputStream fis = null; BufferedInputStream bis = null; try { fis = new FileInputStream(file); bis = new BufferedInputStream(fis); ServletOutputStream sos = response.getOutputStream(); int i = bis.read(buffer); while (i != -1) { sos.write(buffer, 0, i); i = bis.read(buffer); } } catch (Exception e) { e.printStackTrace(); } finally { if (fis != null) { try { fis.close(); } catch (Exception e) { e.printStackTrace(); } } } } } }}
阅读全文
0 0
- java 多线程断点下载
- java 多线程断点下载
- Java---多线程断点下载
- Java--多线程断点下载
- Java 多线程断点下载
- java 多线程断点下载
- java多线程断点下载
- java多线程断点下载
- Java---多线程断点下载
- java多线程断点下载
- JAVA多线程断点下载
- 多线程断点下载----java
- Java多线程、断点下载程序
- Java 多线程断点下载文件
- Java 多线程断点下载文件
- Java 多线程断点下载文件
- Java 多线程断点下载文件
- Java 多线程断点下载文件
- RMAN Catalog 和 Nocatalog 的区别
- 一文入门Python数据分析库Pandas
- 计算机中的堆和和栈(物理内存上的解释)
- STL常用算法: fill,rotate,rotate_copy.
- 大家好
- 多线程断点下载----java
- 【转载】CentOS 7 安装 Kibana 5.x
- 对比三大内容付费工具,你该如何选择?
- ajax在网络断开时,缓存ajax的调用,网络连接时,恢复ajax调用
- Struts框架demo测试的时候报错:org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFil
- SEO站内优化与站外优化有什么区别
- 织梦cms三级栏目权限管理修改
- 基础练习 时间转换
- Caffe-Python接口常用API参考