`
zqb666kkk
  • 浏览: 733786 次
  • 性别: Icon_minigender_1
  • 来自: 宁波
社区版块
存档分类
最新评论

多线程断点下载文件

    博客分类:
  • java
 
阅读更多
所谓多线程断点下载 :就是当某个文件下了一部分后突然断电了,或者下载程序暂停了,再次运行下载 可以继续下载,而不是重新下载 的一个执行过程。

基本模拟了迅雷下载的原理

本次功能用java实现 :

利用txt文件记录下载的状态  如果在安卓端的话 可以改成用数据库记录下载状态

本程序可以扩展为具有良好用户体验的 下载程序

package mutiDownload;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

/**
 * 多线程断点下载文件
 * 
 * @author Administrator
 * 
 */
public class BreakpointDoloadDemo {

	public  static int threadcount = 3;
	public  static int threadRunning = 3;
	
	
	
	public static void main(String[] args) throws IOException {
		// TODO Auto-generated method stub

		// 获取服务器上的文件长度,在本地创建一个和服务器上的文件一样大的临时文件
		String pathString = "http://192.168.1.84:8091/androidServer/test.mkv";
		URL url = new URL(pathString);
		HttpURLConnection connection = (HttpURLConnection) url.openConnection();
		connection.setConnectTimeout(5000);
		connection.setRequestMethod("GET");
		int code = connection.getResponseCode();
		if (code == 200) { // 请求成功
			int length = connection.getContentLength();
			System.out.println("文件长度:" + length);
			RandomAccessFile ref = new RandomAccessFile("test.mkv", "rwd");
			// 指定创建的临时文件的长度
			ref.setLength(length);
			ref.close();

			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 Downhread(threadId, startIndex, endIndex, pathString)
						.start();
				;

			}
		} else {
			System.out.println("服务器错误");
		}

	}

	/**
	 * 下载文件子线程
	 * 
	 * @author Administrator
	 * 
	 */
	public static class Downhread extends Thread {
		private int threadId;
		private int startIndex;
		private int endIndex;
		private String path;

		/**
		 * 
		 * @param threadId
		 *            线程id
		 * @param startIndex
		 *            线程下载的开始位置
		 * @param endIndex
		 * @param path
		 *            下载文件在服务器上的位置
		 */
		public Downhread(int threadId, int startIndex, int endIndex, String path) {
			super();
			this.threadId = threadId;
			this.startIndex = startIndex;
			this.endIndex = endIndex;
			this.path = path;
		}

		@Override
		public void run() {
			// TODO Auto-generated method stub
			// super.run();
			try {
				
				//检查是否存在记录下载长度的文件,如果存在读取文件的数据
				File tempFile=new File(threadId+".txt");
				if(tempFile.exists()&&tempFile.length()>0){
					FileInputStream fis=new FileInputStream(tempFile);
					byte [] temp=new byte[1024];
					int leng=fis.read(temp);
					String downloadLen=new String(temp,0,leng);
					int downloadInt=Integer.parseInt(downloadLen);
					startIndex=downloadInt;	//修改下载的真实开始位置
				}
				
				
				
				
				URL url = new URL(path);
				HttpURLConnection connection = (HttpURLConnection) url
						.openConnection();
				connection.setConnectTimeout(5000);
				connection.setRequestMethod("GET");
				connection.setRequestProperty("Range", "bytes=" + startIndex
						+ "-" + endIndex);
				
				System.out.println("线程真实下载位置:" + threadId + "startIndex:" + startIndex+"-->"+endIndex);
				int code = connection.getResponseCode();
				System.out.println("code:" + code);
				// if(code==200){ //请求成功
				//
				// }
				InputStream is = connection.getInputStream();
				RandomAccessFile raf = new RandomAccessFile("test.mkv", "rwd");
				// 写文件的时候指定从哪个位置开始写
				raf.seek(startIndex);

				int len = 0;
				byte[] buffer = new byte[1024];
				int total = 0; // 已经下载的数据长度
				// File file=new File(threadId+".txt"); //作用:记录当前线程下载的数据长度

				while ((len = is.read(buffer)) != -1) {
					RandomAccessFile file = new RandomAccessFile(threadId
							+ ".txt", "rwd");
					raf.write(buffer, 0, len);
					total += len;
					//System.out.println("线程:" + threadId + "total:" + total);
					file.write(String.valueOf(total+startIndex).getBytes());	//记录下载的位置
					file.close();
				}
				is.close();
				raf.close();
				System.out.println("线程:" + threadId + "下载完毕了...");
				
//			    File delfile =new File(threadId+ ".txt");
//			    delfile.delete();	//当线程下载完毕后清除记录文件
			    
			} catch (MalformedURLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}finally{
				threadRunning--;
				
				if(threadRunning==0){	//所有线程执行完毕
					for(int i=0;i<=3;i++){
						 File file =new File(i+ ".txt");
						 file.delete();
					}
					System.out.println("文件下载完毕,删除所有记录文件");
				}
			}
		}
	}

}
1
2
分享到:
评论

相关推荐

    知攻善防-应急响应靶机-web2.z18

    知攻善防-应急响应靶机-web2.z18

    知攻善防-应急响应靶机-web2.z09

    知攻善防-应急响应靶机-web2.z09

    白色简洁风格的影视众筹平台整站网站源码下载.zip

    白色简洁风格的影视众筹平台整站网站源码下载.zip

    HTTP请求流程深入解析与性能优化技术指南

    内容概要:本文详细解析了HTTP请求的整个流程,包括用户请求发起、请求报文构建、服务器处理请求、响应报文生成、网络传输响应和浏览器接收响应六个阶段。每个阶段的内容均涵盖了关键步骤和技术细节,如DNS解析、TCP连接、缓存策略、HTTP/2性能提升、HTTPS加密等。通过这些内容,读者可以全面理解HTTP请求的完整流程。 适合人群:具备一定网络基础知识的前端、后端开发人员及IT运维人员。 使用场景及目标:适用于希望深入了解HTTP协议及其优化技术的技术人员,有助于提升系统的性能和安全性,优化用户体验。 阅读建议:本文内容详尽且涉及多个关键技术点,建议读者结合实际案例进行学习,逐步理解和掌握各个阶段的技术细节和优化方法。

    白色简洁风格的电话通讯公司模板下载.zip

    白色简洁风格的电话通讯公司模板下载.zip

    白色简洁风格的日历当日事件提醒整站网站源码下载.zip

    白色简洁风格的日历当日事件提醒整站网站源码下载.zip

    RX8 专业消人声 乐器 软件

    一键制作 歌曲伴奏! 可以消人声 吉他 鼓 等 多轨道声音。相当好用。

    知攻善防-应急响应靶机-web2.z04

    知攻善防-应急响应靶机-web2.z04

    NSDocumentError如何解决.md

    NSDocumentError如何解决.md

    白色宽屏风格的大气冲浪运动整站网站模板.rar

    白色宽屏风格的大气冲浪运动整站网站模板.rar

    白色简洁风格的婴儿用品商城网站模板.zip

    白色简洁风格的婴儿用品商城网站模板.zip

    罗兰贝格2023未来营养趋势报告21页

    罗兰贝格2023未来营养趋势报告21页

    html+css 圣诞树代码html

    预览地址:https://blog.csdn.net/qq_42431718/article/details/144749829 html+css 圣诞树代码html

    小学生出题软件v6.3.3.zip

    1-100加减乘除出题生成器

    白色简洁风格的网络实验室CSS模板.zip

    白色简洁风格的网络实验室CSS模板.zip

    白色简洁风格的企业产品展示整站网站源码下载.zip

    白色简洁风格的企业产品展示整站网站源码下载.zip

    etcd服务器性能指标与状态监控数据

    内容概要:《etcd-metrics-latest.txt》文档记录了 etcd(一个分布式键值存储系统)的多个指标数据,包括但不限于集群版本、认证修订版、后端磁盘操作延时分布、租赁管理、键值操作统计、快照保存、网络通信、Go 运行时指标、gRPC 请求处理、操作系统资源使用以及进程资源使用等。这些指标提供了详细的性能监测数据,帮助运维人员和开发人员理解和优化 etcd 集群的运行状态。 适合人群:具有基础计算机科学知识的运维人员或开发人员,尤其是负责维护或开发基于 etcd 技术系统的专业人员。 使用场景及目标:主要用于监控 etcd 集群的健康状况,评估性能瓶颈,辅助故障排查,支持集群的持续优化和技术决策。 其他说明:文档中大量使用了指标和术语,建议读者对 etcd、Go 语言、gRPC 和操作系统基础知识有一定的了解,以便更好地解读文档中的数据。对于不熟悉这些技术的读者来说,可能需要额外查阅相关资料来辅助理解。

    (1866400)java编的计算器程序

    Java编写的计算器程序是一种基于Java编程语言实现的计算工具,常用于教学或个人项目中,以帮助用户执行基本的数学运算。在这个简单的计算器程序中,我们可能会遇到以下几个关键的Java知识点: 1. **基础语法与控制结构**:Java的基础语法包括变量声明、数据类型(如int、double等)、条件语句(if-else)和循环语句(for, while)。在计算器程序中,这些元素用于读取用户输入、判断操作类型以及重复执行某些计算过程。 2. **面向对象编程**:Java是一种面向对象的语言,因此计算器程序可能包含多个类,如Calculator类、Button类(模拟图形界面的按钮)和Display类(显示计算结果)。类之间可能存在继承关系,例如Button类可能继承自一个抽象的UIComponent类。 3. **输入/输出处理**:在命令行计算器中,Java的Scanner类用于获取用户输入,如数字和运算符。在图形用户界面(GUI)计算器中,可能使用事件监听器处理用户的点击事件,获取按钮上的文字信息。 4. **异常处理**:为了确保程序的健壮性,计算器可能包含异常处理代码,比如当

    SystemExit.md

    SystemExit.md

    NavigationGuardError解决办法.md

    NavigationGuardError解决办法.md

Global site tag (gtag.js) - Google Analytics