多线程模拟迅雷下载

知识点:1.运用swt设计下载界面
2.资源用HttpUrlConnection获取,并设置相应属性
3.断点和续传(暂停或关掉界面后,将下载路径、保存路径、文件总长度和以下载长度保存到txt文件中。下次开启时自动去检索有没有为下载完成的文件。)
4.续传时,请求头换setRequestProperty(“Range”, “bytes=” + start + “-” + totalSize),即从断点那里开始,下面的输入流也相应跳过以下载长度。
具体代码如下:
界面类:
public class XunLei {
private Display display;
protected Shell shell;
private Text text;
private Table table;
private Task task;
private Thread thread;
private ProgressBar bar;
private int totalSize;
private int size;
private String path;
private String url;
private Map map = new HashMap();
/**
*** Launch the application.
* @param args
/
public static void main(String[] args) {
try {
XunLei window = new XunLei();
window.open();
} catch (Exception e) {
e.printStackTrace();
}
}
*
/**
* Open the window.
/
public void open() {
display = Display.getDefault();
createContents();
shell.open();
shell.layout();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
}
/
*
* Create contents of the window.
*/
protected void createContents() {
shell = new Shell(SWT.MIN);

		shell.setImage(SWTResourceManager.getImage(XunLei.class, "/images/yc.png"));
		shell.setSize(900,600);
		shell.setText("迅雷下载工具");
		shell.setLayout(new FillLayout(SWT.HORIZONTAL));
		shell.setLocation((display.getClientArea().width-shell.getSize().x)/2, (display.getClientArea().height-shell.getSize().y)/2);
		Composite composite = new Composite(shell, SWT.NONE);
		composite.setLayout(new FillLayout(SWT.HORIZONTAL));
		SashForm sashForm = new SashForm(composite, SWT.NONE);
		sashForm.setOrientation(SWT.VERTICAL);
		Composite composite_1 = new Composite(sashForm, SWT.NONE);
		Label lblNewLabel = new Label(composite_1, SWT.NONE);
		lblNewLabel.setBounds(20, 12, 61, 17);
		lblNewLabel.setText("下载地址:");
		text = new Text(composite_1, SWT.BORDER);
		text.setText("https://dl.360safe.com/360sd/360sd_std_5.0.0.8061.exe");
		text.setBounds(88, 10, 692, 23);
		Button btnNewButton = new Button(composite_1, SWT.NONE);
		btnNewButton.setBounds(793, 7, 80, 27);
		btnNewButton.setText("下载");
		Composite composite_2 = new Composite(sashForm, SWT.NONE);
		composite_2.setLayout(new FillLayout(SWT.HORIZONTAL));
		table = new Table(composite_2, SWT.BORDER | SWT.FULL_SELECTION);
		table.setHeaderVisible(true);
		table.setLinesVisible(true);
		TableColumn tblclmnNewColumn = new TableColumn(table, SWT.NONE);
		tblclmnNewColumn.setWidth(287);
		tblclmnNewColumn.setText("                          下载地址");
		TableColumn tblclmnNewColumn_2 = new TableColumn(table, SWT.CENTER);
		tblclmnNewColumn_2.setWidth(242);
		tblclmnNewColumn_2.setText("保存路径");
		TableColumn tblclmnNewColumn_1 = new TableColumn(table, SWT.CENTER);
		tblclmnNewColumn_1.setWidth(271);
		tblclmnNewColumn_1.setText("下载进度");
		TableColumn tblclmnNewColumn_3 = new TableColumn(table, SWT.CENTER);
		tblclmnNewColumn_3.setWidth(88);
		tblclmnNewColumn_3.setText("状态");
		final TableCursor tableCursor = new TableCursor(table, SWT.NONE);
		Menu menu = new Menu(tableCursor);
		tableCursor.setMenu(menu);
		final MenuItem menuItem = new MenuItem(menu, SWT.NONE);
		menuItem.setText("暂停");
		MenuItem menuItem_1 = new MenuItem(menu, SWT.NONE);
		menuItem_1.setText("删除");
		final MenuItem mntmNewItem = new MenuItem(menu, SWT.NONE);
		mntmNewItem.setText("继续");
		sashForm.setWeights(new int[] {52, 517});
		File file = new File("D:\\xunlei");
		if (file.exists()) {
			File[] files = file.listFiles();
			TableItem ti = null;
			for (File f : files) {
				if (f.isFile()) {
					try {
						BufferedReader br = new BufferedReader(new FileReader(f));
						ti = new TableItem(table, SWT.NONE);
						url = br.readLine();
						ti.setText(0,url);
						ti.setData("url", url);
						ti.setText(1,br.readLine());
						TableEditor ted = new TableEditor(table);
						bar = new ProgressBar(table, SWT.NONE);
						bar.setMinimum(0);
						bar.setMaximum(100);
						ti.setData("bar", bar);
						ted.grabHorizontal = true;
						ted.grabVertical = true;
						ted.setEditor(bar, ti, 2);
						totalSize = Integer.parseInt(br.readLine());
						size = Integer.parseInt(br.readLine());
						ti.setData("size", size);
						ti.setData("totalSize", totalSize);
						int count = (int)((size/(float)totalSize)*100);
						bar.setSelection( count);
						ti.setText(3, "已暂停");
						br.close();
						f.delete();
					} catch (FileNotFoundException e1) {
						e1.printStackTrace();
					} catch (IOException e1) {
						e1.printStackTrace();
					}
				}
			}
		}
		
		btnNewButton.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				url = text.getText().trim();
				if (url == null || "".equals(url)) {
					MessageDialog.openError(shell, "温馨提示", "请输入你要下载的资源地址...");
					return;
				}
				DirectoryDialog fd = new DirectoryDialog(shell, SWT.SAVE);
				fd.setText("下载路径选择");
				fd.setFilterPath("SystemDrive");
				fd.setMessage("请选择你要保存的路径");
				path = fd.open();
				if (path == null || "".equals(path)) {
					return;
				}
				// 开启启动下载任务
				task = new Task(url, path, table);
				map.put(url.substring(url.lastIndexOf("/") + 1), task);
				thread = new Thread(task);
				thread.start();
			}
		});
		menuItem.addSelectionListener(new SelectionAdapter() {
			@SuppressWarnings("deprecation")
			@Override
			public void widgetSelected(SelectionEvent e) {  // 暂停
				TableItem ti = tableCursor.getRow();
				task.save(ti, thread);
				thread.stop();
			}
		});
		mntmNewItem.addSelectionListener(new SelectionAdapter() {  // 继续
			@Override
			public void widgetSelected(SelectionEvent e) {
				TableItem ti = tableCursor.getRow();
				task = new Task(String.valueOf(ti.getData("url")), ti.getText(1), table, ti, Integer.parseInt(String.valueOf(ti.getData("size"))), Integer.parseInt(String.valueOf(ti.getData("totalSize"))),(ProgressBar)ti.getData("bar"));
				ti.setText(3, "正在下载");
				File file = new File("D:\\xunlei");
				if (file.exists()) {
					File[] files = file.listFiles();
					for (File f : files) {
						f.delete();
					}
				}
				thread = new Thread(task);
				thread.start();
			}
		});
		shell.addShellListener(new ShellAdapter() {
			@Override
			public void shellClosed(ShellEvent e) {
				TableItem[] tis = table.getItems();
				for (TableItem ti : tis) {
					if ("正在下载".equals(ti.getText(3))) {
						task.save(ti, thread);
					}
				}
			}
		});
	}
}

线程类:

public class Task implements Runnable{
	private String urlPath;
	private String savePath;
	private Table table;
	private ProgressBar bar;
	private TableItem ti;
	private String fileName;
	private int totalSize = 0;
	private int size = 0;
	private int start = 0;
	private boolean flag = true;
	private boolean isPause = false;
	public Task(String urlPath, String savePath, Table table) {
		this.urlPath = urlPath;
		this.fileName = urlPath.substring(urlPath.lastIndexOf("/") + 1);
		this.savePath = savePath + "\\" + fileName;
		this.table = table;
		flag = true;
		start = 0;
	}
	public Task(String urlPath, String savePath, Table table, TableItem ti, int start, int totalSize, ProgressBar bar) {
		this.urlPath = urlPath;
		this.fileName = urlPath.substring(urlPath.lastIndexOf("/") + 1);
		this.savePath = savePath;
		this.table = table;
		this.ti = ti;
		this.start = start + 1;
		this.size = start;
		this.totalSize = totalSize;
		this.bar = bar;
		flag = false;
		ti.setData("totalSize", totalSize);
	}
	@Override
	public void run() {
		table.getDisplay().asyncExec(new Runnable(){
			@Override
			public void run() {
				if (flag) {
					ti = new TableItem(table, SWT.NONE);
					ti.setText(0, fileName);
					ti.setData("url", urlPath);
					ti.setText(1, savePath);
					ti.setText(3, "正在下载");
					TableEditor ted = new TableEditor(table);
					bar = new ProgressBar(table, SWT.NONE);
					bar.setMinimum(0);
					bar.setMaximum(100);
					
					ted.grabHorizontal = true;
					ted.grabVertical = true;
					
					ted.setEditor(bar, ti, 2);
					ti.setData("bar", bar);
				}
			}
		});
		FileOutputStream fos = null;
		InputStream is = null;
		HttpURLConnection con = null;
		try {
			URL url = new URL(urlPath);
			con = (HttpURLConnection) url.openConnection();
			con.setRequestMethod("GET");
			con.setConnectTimeout(5 * 1000);
			if (flag) {
				con.connect();
				totalSize = con.getContentLength();	
				Display.getDefault().asyncExec(new Runnable() {
					@Override
					public void run() {
						ti.setData("totalSize", totalSize);
					}
				});
			} else {
				 con.setRequestProperty("Range", "bytes=" + start + "-" + totalSize); 
				 con.setUseCaches(true);
			} 
			is = con.getInputStream();
			RandomAccessFile raf = new RandomAccessFile(savePath, "rwd");
			//[6]每个线程要从自己的位置开始写 
			raf.seek(start);
			//[7]把数据写到文件中
			int len = -1;
			byte[] buffer = new byte[1024*1024];//1Mb
			while((len = is.read(buffer))!=-1){
				raf.write(buffer, 0, len);
				size += len;
				Display.getDefault().asyncExec(new Runnable() {
					@Override			
					public void run() {
						int count = (int)((size/(float)totalSize)*100);
						bar.setSelection( count);
						if (count == 100) {
							ti.setText(3, "已下载");
						}
						// 保存已下载大小
						ti.setData("size", size);
					}
				});
			}
			raf.close();//关闭流  释放资源		
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (is != null) {
				try {
					is.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (con != null) {
				con.disconnect(); 
			}
		}
	}
	public void save(TableItem ti, Thread thread) {
		File file = new File("D:\\xunlei");
		if (!file.exists()) {
			file.mkdir();
		}
		ti.setText(3, "已暂停");
		try {
			BufferedWriter bw = new BufferedWriter(new FileWriter("D:\\xunlei\\"+fileName+".txt"));
			bw.write(String.valueOf(ti.getData("url"))+"\r\n");
			bw.write(ti.getText(1)+"\r\n");
			bw.write(String.valueOf(ti.getData("totalSize"))+"\r\n");
			bw.write(String.valueOf(ti.getData("size")));
			bw.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

你可能感兴趣的:(线程)