当前位置:首页 » JAVA技术教程

【JAVA之多线程下载文件实现】

2018-03-11 11:20 本站整理 浏览(7)

1、准备待下载文件


 

2、准备下载地址


 

三、核心代码

 

/**
 * JAVA 多线程实现文件下载
 * @author gaojignsong
 *
 */
public class MultiDownload {
	public static String path = "http://localhost:8080/upload/G4Studio.pdf";// 下载文件的路径
	public static String store = "E:/C/G4.pdf";// 文件存储路径
	public static String temp = "E:/C/";// 临时文件的存储路径
	public static String method = "GET";
	public static int threadNum = 5;// 设置开启的线程数量

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		HttpURLConnection connection = getConnection(path, method);
		try {
			connection.connect();// 打开连接
			if (connection.getResponseCode() == 200) {
				// 获取文件的大小
				int length = connection.getContentLength();
				System.out.println(length);
				File file = new File(store);
				// 生成临时文件
				RandomAccessFile raf = new RandomAccessFile(file, "rwd");
				// 设置临时文件的大小
				raf.setLength(length);
				int blockSize  = length / threadNum;
				for (int i = 0; i < threadNum; i++) {
					int startIndex = i * blockSize ;
					int endIndex = (i + 1) * blockSize  - 1;
					if (i == threadNum - 1)
						endIndex = length - 1;
					System.out.println("start: " + startIndex + " end: "+ endIndex);
					new DownloadThread(startIndex, endIndex, i).start();
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

	/**
	 * 获取连接
	 * @param path
	 * @return
	 */
	public static HttpURLConnection getConnection(String path, String method) {
		HttpURLConnection connection = null;
		try {
			URL url = new URL(path);
			connection = (HttpURLConnection) url.openConnection();
			connection.setReadTimeout(6000);// 设置读取超时时间
			connection.setConnectTimeout(6000);// 设置连接超时时间
			connection.setRequestMethod(method);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return connection;
	}

}

class DownloadThread extends Thread {
	public int startIndex;
	public int endIndex;
	public int threadId;

	public DownloadThread(int startIndex, int endIndex, int threadId) {
		this.startIndex = startIndex;
		this.endIndex = endIndex;
		this.threadId = threadId;
	}

	@Override
	public void run() {
		//创建保存下载进度的临时文件 
		File progressFile = new File(MultiDownload.temp + threadId + ".txt");
		//如果进度临时文件存在 
		if (progressFile.exists()) {
			try {
				BufferedReader reader = new BufferedReader(new FileReader(progressFile));
				//从进度临时文件中读取出上一次下载的总进度  
                //然后与原本的开始位置相加,得到新的开始位置 
				startIndex +=  Integer.parseInt(reader.readLine());// 计算出断点需要开始下载的字节位置
				reader.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		HttpURLConnection connection = MultiDownload.getConnection(
				MultiDownload.path, MultiDownload.method);
		//设置本次http请求所请求的数据的区间 
		connection.setRequestProperty("RANGE", "bytes=" + startIndex + "-"+ endIndex);
		try {
			connection.connect();
			int code = connection.getResponseCode();
			System.out.println(code);
            
			//创建一个临时文件 ,拿到临时文件的输出流  
			RandomAccessFile randomAccessFile = new RandomAccessFile(new File(MultiDownload.store), "rw");
			//把文件的写入位置移动至startIndex 
			randomAccessFile.seek(startIndex);
			//200:请求全部资源成功  206:代表部分资源请求成功
			if (connection.getResponseCode() == 206) {
				InputStream is = connection.getInputStream();
				byte[] buffer = new byte[2048];
				int len = 0;
				int total = 0;
				while ((len = is.read(buffer)) != -1) {
					//每次读取流里数据之后,同步把数据写入临时文件 
					randomAccessFile.write(buffer, 0, len);
					total += len;
					//将执行进度写入临时文件中,生成一个专门用来记录下载进度的临时文件
					RandomAccessFile tempRaf = new RandomAccessFile(progressFile, "rwd");
					tempRaf.write((total + "").getBytes());
					tempRaf.close();
				}
			}
			// 只要线程执行到这一步的话,就已经表明他已经完成了自己应该爬取的字节范围啦,所以要删除临时文件
			progressFile.delete();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}


 

四、结果验证