1.package download;import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Observable;/*
* 执行具体下载任务的类
*/
class Download extends Observable implements Runnable {
private static final int MAX_BUFFER_SIZE = 1024; public static final String STATUSES[] = { "Downloading", "Pause",
"Complete", "Canceled", "ERROR" };
public static final int DOWNLOADING = 0;
public static final int PAUSED = 1;
public static final int COMPLETE = 2;
public static final int CANCELED = 3;
public static final int ERROR = 4;
/*
* 目标文件的下载地址
*/
private URL url; /*
* 目标文件的大小
*/
private int size; /*
* 已下载的字节数
*/
private int downloaded; /*
* 当前的下载状态
*/
private int status; /*
* 构造函数,完成变量的初始化
*/
public Download(URL url) {
this.url = url;
size = -1;
downloaded = 0;
status = DOWNLOADING;
download();
} /*
* 返回url
*/
public String getUrl() {
return url.toString();
}
public int getSize() {
return size;
}
/*
* 返回下载进度
*/
public float getProgress() {
return ((float) downloaded / size) * 100;
} /*
* 返回下载状态
*/
public int getStatus() {
return status;
} /*
* 暂停
*/
public void pause() {
status = PAUSED;
stateChanged();
}
/*
* 恢复
*/
public void resume() {
status = DOWNLOADING;
stateChanged();
download();
}
/*
* 取消
*/
public void cancel() {
status = CANCELED;
stateChanged();
}
/*
* 下载任务出错
*/
public void error() {
status = ERROR;
stateChanged();
}
/*
* 增加一个线程,开始下载
*/
private void download() {
Thread thread = new Thread(this);
thread.start();
}
private String getFileName(URL url) {
String fileName = url.getFile();
return fileName.substring(fileName.lastIndexOf('/') + 1);
}
/*
* 执行下载任务
*/
public void run() {
RandomAccessFile file = null;
InputStream stream = null;
try {
HttpURLConnection connection = (HttpURLConnection) url
.openConnection(); connection.setRequestProperty("Range", "bytes=" + downloaded + "-");
connection.connect();
if (connection.getResponseCode() / 100 != 2) {
error();
}
int contentLength = connection.getContentLength();
if (contentLength < 1) {
error();
}
if (size == -1) {
size = contentLength;
stateChanged();
}
file = new RandomAccessFile(getFileName(url), "rw");
file.seek(downloaded);
stream = connection.getInputStream();
while (status == DOWNLOADING) {
byte buffer[];
if (size - downloaded > MAX_BUFFER_SIZE) {
buffer = new byte[MAX_BUFFER_SIZE];
} else {
buffer = new byte[size - downloaded];
} int read = stream.read(buffer); if (read == -1) {
break;
}
file.write(buffer, 0, read);
downloaded += read;
stateChanged();
}
if (status == DOWNLOADING) {
status = COMPLETE;
stateChanged();
}
} catch (Exception e) {
error();
} finally {
if (file != null) {
try {
file.close();
} catch (Exception e) {
e.printStackTrace();
}
}
if (stream != null) {
try {
stream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
/*
* 通知observer,下载状态改变了
*/
private void stateChanged() {
setChanged();
notifyObservers();
}
}
2.package download;
import java.util.ArrayList;
import java.util.Observable;
import java.util.Observer;
import javax.swing.JProgressBar;
import javax.swing.table.AbstractTableModel;
/*
* 下载管理器的主要工作由Download类完成。Download类的主要
工作是下载一个文件并将其内容保存到磁盘。每次向下载管理器
添加一项下载任务时,就会有一个新的Download对象被实力化,
以便处理这个下载任务。
下载管理器具有同时下载多个文件的能力,而每个同时进行的下载任务都必须独立运行,
且每个下载还必须管理自己的状态,以便反映在GUI中。这个工作也通过Download类来完成。
*/
class DownloadsTableModel extends AbstractTableModel implements Observer {
public static final long serialVersionUID = 223; private static final String[] columnNames = { "URL", "Size", "Progress",
"Status" };
private static final Class[] columnClasses = { String.class, String.class,
JProgressBar.class, String.class };
private ArrayList<Download> downloadList;
public DownloadsTableModel() {
downloadList = new ArrayList<Download>();
}
/*
* 添加一个新的Download对象到下载任务列表中,表格因此新增一行
*/
public void addDownload(Download download) {
download.addObserver(this);
downloadList.add(download);
fireTableRowsInserted(getRowCount() - 1, getRowCount() - 1);
}
public Download getDownload(int row) {
return downloadList.get(row);
}
/*
* 从下载列表中删除一个Download
*/
public void clearDownload(int row) {
downloadList.remove(row);
fireTableRowsDeleted(row, row);
}
public int getColumnCount() {
return columnNames.length;
}
public String getColumnName(int col) {
return columnNames[col];
}
public Class<?> getColumnClass(int col) {
return columnClasses[col];
} public int getRowCount() {
return columnNames.length;
}
public Object getValueAt(int row, int col) {
try {
Download download = (Download) downloadList.get(row);
switch (col) {
case 0://
return download.getUrl();
case 1:
int size = download.getSize();
return (size == -1) ? "" : Integer.toString(size);
case 2:
return new Float(download.getProgress());
case 3:
return Download.STATUSES[download.getStatus()];
default:
break;
}
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
public void update(Observable o, Object arg) { int index = downloadList.indexOf(o); fireTableRowsUpdated(index, index);
}}
3.package download;import java.awt.Component;
import javax.swing.JProgressBar;
import javax.swing.JTable;
import javax.swing.table.TableCellRenderer;/*
* ProgressRenderer类是一个小小的工具类,
*用于显示GUI的“Downloads”JTtable实例中的下载任务的进度
*/
class ProgressRenderer extends JProgressBar implements TableCellRenderer {
public static final long serialVersionUID = 23; public ProgressRenderer(int min, int max) {
super(min, max);
} public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
setValue((int) ((Float) value).floatValue());
return this;
}
}
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Observable;/*
* 执行具体下载任务的类
*/
class Download extends Observable implements Runnable {
private static final int MAX_BUFFER_SIZE = 1024; public static final String STATUSES[] = { "Downloading", "Pause",
"Complete", "Canceled", "ERROR" };
public static final int DOWNLOADING = 0;
public static final int PAUSED = 1;
public static final int COMPLETE = 2;
public static final int CANCELED = 3;
public static final int ERROR = 4;
/*
* 目标文件的下载地址
*/
private URL url; /*
* 目标文件的大小
*/
private int size; /*
* 已下载的字节数
*/
private int downloaded; /*
* 当前的下载状态
*/
private int status; /*
* 构造函数,完成变量的初始化
*/
public Download(URL url) {
this.url = url;
size = -1;
downloaded = 0;
status = DOWNLOADING;
download();
} /*
* 返回url
*/
public String getUrl() {
return url.toString();
}
public int getSize() {
return size;
}
/*
* 返回下载进度
*/
public float getProgress() {
return ((float) downloaded / size) * 100;
} /*
* 返回下载状态
*/
public int getStatus() {
return status;
} /*
* 暂停
*/
public void pause() {
status = PAUSED;
stateChanged();
}
/*
* 恢复
*/
public void resume() {
status = DOWNLOADING;
stateChanged();
download();
}
/*
* 取消
*/
public void cancel() {
status = CANCELED;
stateChanged();
}
/*
* 下载任务出错
*/
public void error() {
status = ERROR;
stateChanged();
}
/*
* 增加一个线程,开始下载
*/
private void download() {
Thread thread = new Thread(this);
thread.start();
}
private String getFileName(URL url) {
String fileName = url.getFile();
return fileName.substring(fileName.lastIndexOf('/') + 1);
}
/*
* 执行下载任务
*/
public void run() {
RandomAccessFile file = null;
InputStream stream = null;
try {
HttpURLConnection connection = (HttpURLConnection) url
.openConnection(); connection.setRequestProperty("Range", "bytes=" + downloaded + "-");
connection.connect();
if (connection.getResponseCode() / 100 != 2) {
error();
}
int contentLength = connection.getContentLength();
if (contentLength < 1) {
error();
}
if (size == -1) {
size = contentLength;
stateChanged();
}
file = new RandomAccessFile(getFileName(url), "rw");
file.seek(downloaded);
stream = connection.getInputStream();
while (status == DOWNLOADING) {
byte buffer[];
if (size - downloaded > MAX_BUFFER_SIZE) {
buffer = new byte[MAX_BUFFER_SIZE];
} else {
buffer = new byte[size - downloaded];
} int read = stream.read(buffer); if (read == -1) {
break;
}
file.write(buffer, 0, read);
downloaded += read;
stateChanged();
}
if (status == DOWNLOADING) {
status = COMPLETE;
stateChanged();
}
} catch (Exception e) {
error();
} finally {
if (file != null) {
try {
file.close();
} catch (Exception e) {
e.printStackTrace();
}
}
if (stream != null) {
try {
stream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
/*
* 通知observer,下载状态改变了
*/
private void stateChanged() {
setChanged();
notifyObservers();
}
}
2.package download;
import java.util.ArrayList;
import java.util.Observable;
import java.util.Observer;
import javax.swing.JProgressBar;
import javax.swing.table.AbstractTableModel;
/*
* 下载管理器的主要工作由Download类完成。Download类的主要
工作是下载一个文件并将其内容保存到磁盘。每次向下载管理器
添加一项下载任务时,就会有一个新的Download对象被实力化,
以便处理这个下载任务。
下载管理器具有同时下载多个文件的能力,而每个同时进行的下载任务都必须独立运行,
且每个下载还必须管理自己的状态,以便反映在GUI中。这个工作也通过Download类来完成。
*/
class DownloadsTableModel extends AbstractTableModel implements Observer {
public static final long serialVersionUID = 223; private static final String[] columnNames = { "URL", "Size", "Progress",
"Status" };
private static final Class[] columnClasses = { String.class, String.class,
JProgressBar.class, String.class };
private ArrayList<Download> downloadList;
public DownloadsTableModel() {
downloadList = new ArrayList<Download>();
}
/*
* 添加一个新的Download对象到下载任务列表中,表格因此新增一行
*/
public void addDownload(Download download) {
download.addObserver(this);
downloadList.add(download);
fireTableRowsInserted(getRowCount() - 1, getRowCount() - 1);
}
public Download getDownload(int row) {
return downloadList.get(row);
}
/*
* 从下载列表中删除一个Download
*/
public void clearDownload(int row) {
downloadList.remove(row);
fireTableRowsDeleted(row, row);
}
public int getColumnCount() {
return columnNames.length;
}
public String getColumnName(int col) {
return columnNames[col];
}
public Class<?> getColumnClass(int col) {
return columnClasses[col];
} public int getRowCount() {
return columnNames.length;
}
public Object getValueAt(int row, int col) {
try {
Download download = (Download) downloadList.get(row);
switch (col) {
case 0://
return download.getUrl();
case 1:
int size = download.getSize();
return (size == -1) ? "" : Integer.toString(size);
case 2:
return new Float(download.getProgress());
case 3:
return Download.STATUSES[download.getStatus()];
default:
break;
}
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
public void update(Observable o, Object arg) { int index = downloadList.indexOf(o); fireTableRowsUpdated(index, index);
}}
3.package download;import java.awt.Component;
import javax.swing.JProgressBar;
import javax.swing.JTable;
import javax.swing.table.TableCellRenderer;/*
* ProgressRenderer类是一个小小的工具类,
*用于显示GUI的“Downloads”JTtable实例中的下载任务的进度
*/
class ProgressRenderer extends JProgressBar implements TableCellRenderer {
public static final long serialVersionUID = 23; public ProgressRenderer(int min, int max) {
super(min, max);
} public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
setValue((int) ((Float) value).floatValue());
return this;
}
}
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.net.URL;
import java.util.Observable;
import java.util.Observer;import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;/*
* 创建并运行下载管理器的GUI
*/
public class DownloadManager extends JFrame implements Observer {
public static final long serialVersionUID = 23; private JTextField url; private DownloadsTableModel tableModel; private JTable table;
private JButton pauseButton, resumeButton;
private JButton cancelButton, clearButton;
private Download selectedDownload;
private boolean clearing;
JPanel addPanel;
JPanel downloadPanel;
JPanel buttonsPanel; public DownloadManager() {
setTitle("Fans Download");
setSize(640, 480);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
actionExit();
}
});
initMenu();
initPanel(); Container container = getContentPane();
container.setLayout(new BorderLayout());
container.setLayout(new BorderLayout());
container.add(addPanel, BorderLayout.NORTH);
container.add(downloadPanel, BorderLayout.CENTER);
container.add(buttonsPanel, BorderLayout.SOUTH);
} private void initMenu() {
// 创建菜单
JMenuBar menuBar = new JMenuBar();
JMenu fileMenu = new JMenu("File");
fileMenu.setMnemonic(KeyEvent.VK_F);
JMenuItem fileExit = new JMenuItem("退出", KeyEvent.VK_X);
fileExit.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
actionExit();
}
});
fileMenu.add(fileExit);
setJMenuBar(menuBar);
} private void initPanel() { /*
* 添加下载任务的面板
*/
addPanel = new JPanel();
url = new JTextField(30);
addPanel.add(url);
JButton addButton = new JButton("添加下载任务");
addButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
actionAdd();
}
});
addPanel.add(addButton); tableModel = new DownloadsTableModel();
table = new JTable(tableModel);
table.getSelectionModel().addListSelectionListener(
new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
tableSelectionChanged();
}
}); table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
ProgressRenderer renderer = new ProgressRenderer(0, 100);
renderer.setStringPainted(true);
table.setDefaultRenderer(JProgressBar.class, renderer);
table.setRowHeight((int) renderer.getPreferredSize().getHeight()); /*
* 下载面板
*/
downloadPanel = new JPanel();
downloadPanel.setBorder(BorderFactory.createTitledBorder("Downloads"));
downloadPanel.setLayout(new BorderLayout());
downloadPanel.add(new JScrollPane(table), BorderLayout.CENTER); /*
* 按钮面板
*/
buttonsPanel = new JPanel();
pauseButton = new JButton("暂停");
resumeButton = new JButton("恢复");
cancelButton = new JButton("取消");
clearButton = new JButton("清除");
buttonsPanel.add(pauseButton);
buttonsPanel.add(resumeButton);
buttonsPanel.add(cancelButton);
buttonsPanel.add(clearButton);
}
/*
* 验证URL的有效性
*/
private URL verifyUrl(String url) {
if (!url.toLowerCase().startsWith("http://")) {
return null;
} URL verifiedUrl = null;
try {
verifiedUrl = new URL(url);
} catch (Exception e) {
e.printStackTrace();
} if (verifiedUrl.getFile().length() < 2) {
return null;
}
return verifiedUrl;
}
/*
* 退出
*/
private void actionExit() {
System.exit(1);
}
/*
* 增加
*/
private void actionAdd() { URL verifiedUrl = verifyUrl(url.getText());
if (verifiedUrl != null) {
tableModel.addDownload(new Download(verifiedUrl));
url.setText("");
} else {
JOptionPane.showMessageDialog(this, "Invalid Download URL",
"Urror", JOptionPane.ERROR_MESSAGE);
}
}
private void tableSelectionChanged() {
if (selectedDownload != null) {
selectedDownload.deleteObserver(DownloadManager.this);
;
if (!clearing && table.getSelectedRow() > -1) {
selectedDownload = tableModel.getDownload(table
.getSelectedRow());
selectedDownload.addObserver(DownloadManager.this);
updateButtons();
}}} /*
* 暂停
*/
private void actionPause() {
selectedDownload.pause();
updateButtons();
}
/*
* 恢复
*/
private void actionResume() {
selectedDownload.resume();
updateButtons();
}
/*
* 取消下载任务
*/
private void actionCancel() {
selectedDownload.cancel();
updateButtons();
}
private void actionClear() {
clearing = true;
tableModel.clearDownload(table.getSelectedRow());
clearing = false;
selectedDownload = null;
updateButtons();
} /*
* 根据选定的下载项的状态更新按钮状态
*/
private void updateButtons() {
if (selectedDownload != null) {
int status = selectedDownload.getStatus();
switch (status) { case (Download.DOWNLOADING):
pauseButton.setEnabled(true);
resumeButton.setEnabled(false);
cancelButton.setEnabled(true);
clearButton.setEnabled(false);
break;
case Download.PAUSED:
pauseButton.setEnabled(false);
resumeButton.setEnabled(true);
cancelButton.setEnabled(true);
clearButton.setEnabled(false);
break;
case Download.ERROR:
pauseButton.setEnabled(false);
resumeButton.setEnabled(true);
cancelButton.setEnabled(true);
clearButton.setEnabled(false);
break;
default:
pauseButton.setEnabled(false);
resumeButton.setEnabled(false);
cancelButton.setEnabled(false);
clearButton.setEnabled(true);
break;
}
} else {
pauseButton.setEnabled(false);
resumeButton.setEnabled(false);
cancelButton.setEnabled(false);
clearButton.setEnabled(false);
}
} public void update(Observable o, Object arg) {
if (selectedDownload != null && selectedDownload.equals(o)) {
updateButtons();
}
} public static void main(String[] args) {
DownloadManager manager = new DownloadManager();
manager.setVisible(true);
}
}
at java.util.ArrayList.RangeCheck(Unknown Source)
at java.util.ArrayList.get(Unknown Source)
at download.DownloadsTableModel.getValueAt(DownloadsTableModel.java:96)