欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

多线程模拟迅雷下载

程序员文章站 2022-05-31 14:15:57
...

知识点: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<String, Task> map = new HashMap<String, Task>();
/**
* 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();
	}
}

}

相关标签: 线程