多线程下载文件的实现

package cn.itcast.download;

import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;

import java.net.URL;


public class testDownlaod {
public static final String path="http://192.168.1.106:8080/youdao.exe";
public static void main(String[]args) throws Exception{
	URL url=new URL(path);
	HttpURLConnection conn=(HttpURLConnection) url.openConnection();
	conn.setRequestMethod("GET");
	conn.setConnectTimeout(5000);
	conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1)");
	int code=conn.getResponseCode();
	if(code==200){
		int len=conn.getContentLength();
		RandomAccessFile file=new RandomAccessFile("D://baiduyundownload/"+getFileName(path),"rwd");
		//1.设置本地文件大小跟服务器的文件大小一致
		file.setLength(len);
		//2.假设开启3个线程
		int threadnumber=3;
		int blocksize=len/threadnumber;
		/**
		 * 线程的起始位置分别为
		 * thread1 0~blocksize
		 * thread2 1*blocksize~2*blocksize
		 * thread3 2*blocksize~文件末尾
		 */
		for(int i=0;i<threadnumber;i++){
			int startposition=i*blocksize;
			int endposition=(i+1)*blocksize;
			if(i==(threadnumber-1)){
				//最后一个线程
				endposition=len;
			}
			
			DownLoadTask task = new DownLoadTask(i,path,startposition,endposition);
				task.start();
		}
		
	}
	
	
}

public static String getFileName(String path) {
	// TODO Auto-generated method stub
	int start=path.lastIndexOf("/")+1;
	
	return path.substring(start,path.length());
}
}
 class DownLoadTask extends Thread{
	
	public static final String path="http://192.168.1.106:8080/youdao.exe";
	int threadid;
    String filepath;
    int startposition;
    int endposition;
    
    public DownLoadTask(int threadid,String filepath,int startposition,int endposition){
    	this.threadid=threadid;
    	this.filepath=filepath;
    	this.startposition=startposition;
    	this.endposition=endposition;
    	
    }
    @Override
	public void run() {
		// TODO Auto-generated method stub
		try {
			URL url=new URL(filepath);
			HttpURLConnection conn=(HttpURLConnection) url.openConnection();
			conn.setRequestProperty("Range", "bytes="+startposition+endposition);
			
			conn.setRequestMethod("GET");
			conn.setConnectTimeout(5000);
			conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1)");
			InputStream is=conn.getInputStream();
			RandomAccessFile file=new RandomAccessFile(getFileName(path),"rwd");
			//设置数据从文件哪个位置开始写
			file.seek(startposition);
			byte[]buffer=new byte[1024];
			int len=0;
			//rwd 代表当前读到的服务器数据的位置,同时这个值已经存储的文件位置
			while((len=is.read(buffer))!=-1){
				file.write(buffer,0,len);
			}
			file.close();
			System.out.println("线程" + threadid + "下载完毕");
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		super.run();
		
	}
    public static String getFileName(String path) {
		int start = path.lastIndexOf("/") + 1;
		return path.substring(start, path.length());
	}
}

基本原理:利用URLConnection获取要下载文件的长度、头部等相关信息,并设置响应的头部信息。并且通过URLConnection获取输入流,将文件分成指定的块,每一块单独开辟一个线程完成数据的读取、写入。通过输入流读取下载文件的信息,然后将读取的信息用RandomAccessFile随机写入到本地文件中。同时,每个线程写入的数据都文件指针也就是写入数据的长度,需要保存在一个临时文件中。这样当本次下载没有完成的时候,下次下载的时候就从这个文件中读取上一次下载的文件长度,然后继续接着上一次的位置开始下载。并且将本次下载的长度写入到这个文件中。

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。