Android多线程下载(一)

一、首先建一个java项目,获取服务器上文件的大小,来确定多线程下载时,每个线程的开始和结束位置

static String path="http://192.168.1.141:8080/wps.exe";
	public static void main(String[] args) {
		// TODO Auto-generated method stub

		//获取文件大小,计算每个线程下载的开始和结束位置
		try {
			//创建URL对象 指定我们要访问的网址
			URL url = new URL(path);
			//拿到httpurlconnection对象  用于发送和接受数据
			HttpURLConnection conn = (HttpURLConnection) url.openConnection();
			//设置请求超时时间
			conn.setConnectTimeout(5000);//5秒
			//设置发送请求方式
			conn.setRequestMethod("GET");
			//获取服务器返回的状态码
			int code = conn.getResponseCode();
			//200表明请求成功
			if (code == 200) {
		    //获取服务器文件的大小
				int length=conn.getContentLength();
				System.out.println(length);				
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

二、创建一个大小和服务器一样的文件,提前把空间申请出来

RandomAccessFile randomAccessFile = new RandomAccessFile("temp.exe","rw");
randomAccessFile.setLength(length);

三、每个线程下载的开始与结束

假设3个线程下载10个字节的文件,每个线程a下载的大小为10/3,即a=10/3

第一个线程下载的开始和结束位置是 0*a------1*a-1j即(0-2)

第二个线程下载的开始和结束位置是 1*a------2*a-1j即(3-5)

第三个线程下载的开始和结束位置是 2*a------3*a-1j即(6-8)

剩余一个字节                                 3*a-------9      即(9-9)

从而得出第n个线程下载的开始和结束位置是n*a--------(n+1)*a-1

最后剩余m                                               m*a--------length-1

1、申明变量线程的总数

private static final int threadCount=3;

2、每个线程下载的大小

int blockSize=length/threadCount;

3、计算每个线程下载的开始位置和结束位置

				for (int i = 0; i < threadCount; i++) {
					int startIndex=i*blockSize;
					int endIndex=(i+1)*blockSize-1;
					//特殊情况就是最后一个线程
					if (i==threadCount-1) {
						//说明最后一个线程
						endIndex=length-1;
						
					}
				}

4、定义线程去服务器下载文件

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;
		}

		public void run() {
			// 实现去服务器下载文件的逻辑
			try {
				// 创建URL对象 指定我们要访问的网址
				URL url = new URL(path);
				// 拿到httpurlconnection对象 用于发送和接受数据
				HttpURLConnection conn = (HttpURLConnection) url
						.openConnection();
				// 设置请求超时时间
				conn.setConnectTimeout(5000);// 5秒
				// 设置发送请求方式
				conn.setRequestMethod("GET");
				// 设置一个请求头Range(告诉服务器每个线程下载的开始和结束位置)
				conn.setRequestProperty("Range", "bytes=" + startIndex + "-"
						+ endIndex);

				// 获取服务器返回的状态码
				int code = conn.getResponseCode();
				// 200表明请求成功
				if (code == 206) {// 请求部分资源
					// 获取服务器返回的数据,返回的数据都是流的形式
					// 创建随机读写文件对象
					RandomAccessFile randomAccessFile = new RandomAccessFile(
							"temp.exe", "rw");
					// 每个线程从自己位置开始写
					randomAccessFile.seek(startIndex);
					InputStream in = conn.getInputStream();// 存的wps.exe

					// 把数据写到文件中
					int len = -1;
					byte[] buffer = new byte[1024];
					while ((len = in.read(buffer)) != -1) {
						randomAccessFile.write(buffer, 0, len);
					}
					randomAccessFile.close();// 关闭流 释放资源
					System.out.println("线程id:" + threadId);

				}
			} catch (Exception e) {
				e.printStackTrace();
			}

		}
	}

5、启动线程

DownLoadThread downLoadThread = new DownLoadThread(startIndex, endIndex, i);
downLoadThread.start();

四、断点续传

1、存储已下载的位置

int total=0;//当前线程下载的大小
total += len;
						// 实现断点续传,就是把当前线程下载的位置 给存起来,下载再下载的时候 就是按照上次下载的位置继续下载就可以了
						int currentThreadPosition = startIndex + total;//存到txt中
						//用来存当前线程下的下载位置
						RandomAccessFile raf = new RandomAccessFile(
								"temp.exe", "rwd");
						raf.write(String.valueOf(currentThreadPosition).getBytes());
						raf.close();

2、判断是否下载过,读取位置,然后接着下载

				File file=new File(threadId+".txt");
				if (file.exists()&&file.length()>0) {
					FileInputStream fis=new FileInputStream(file);
					BufferedReader bufr=new BufferedReader(new InputStreamReader(fis));
					String lastPosition=bufr.readLine();//读取出来的内容就是上一次下载的位置
					int lastPositionn=Integer.parseInt(lastPosition);
				    startIndex=lastPositionn;
					System.out.println("线程id:"+threadId+"真实下载的位置"+"---"+startIndex+"---"+endIndex);

					fis.close();
				
				}

3、删除因中断而产生的文件

在获取文件大小的时候设置变量runningThread=threadCount

synchronized (DownLoadThread.class) {
						runningThread--;
						if (runningThread==0) {
							for (int i = 0; i < threadCount; i++) {
								File deltFile=new File(i+".txt");
								deltFile.delete();
							}
						}
					}

五、一般下载到本地的文件名字和服务器名字一样

public  static String getFilename(String path){			
				int start =  path.lastIndexOf("/")+1;
				return path.substring(start);			
			}

六、记得把上面的路径也都修改一下

项目源码:https://download.csdn.net/download/qq_35951882/10371245



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值