多線程斷點下載文件

所謂多線程斷點下載 :就是當某個文件下了一部分後突然斷電了,或者下載程序暫停了,再次運行下載 可以繼續下載,而不是重新下載 的一個執行過程。

基本模擬了迅雷下載的原理

本次功能用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("文件下載完畢,刪除所有記錄文件");
				}
			}
		}
	}

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章