FTP(File Transfer Protocol)就是文件传输协议。通过FTP客户端从远程FTP服务器上拷贝文件到本地计算机称为下载,将本地计算机上的文件复制到远程FTP服务器上称为上传,上传和下载是FTP最常用的两个功能。FTP使用传输层的TCP协议进行传输,因此客户端与服务器之间的连接是可靠的,而且是面向连接,为数据的传输提供了可靠的保证。FTP的目标有以下目标:
?
?
?
? 提高文件的共享性 提供非直接地远程操纵计算机 避免用户因主机之间的文件存储系统的差异而导致的变化 为数据的传送提供可靠性和高效性
FTP协议模型如下图所示
FTP使用TCP的服务,它需要两条连接。一条是数据连接用于数据传送,一般使用端口21,而另一条是控制连接用于传送控制信息(命令和
响应),一般使用端口20。控制连接需要传送的只是控制信息,如一行命令或一行应答码,而数据连接需要传送的数据类型繁杂,如文本文件、图形文件、应用程序等等。
FTP协议模型中使用到的交互元素包括用户接口、USERPI、UPTP、SPI、SDTP的说明如
下图所示
FTP传输有两种方式:文本传输模式和二进制数据传输模式。其中文本模式又叫ASCII模
式,二进制模式又叫Binary模式。
FTP服务分为普通FTP与匿名FTP服务两种类型。
常用FTP的命令有:
1) 接入命令
USER: 指明用户名
PASS: 指明与用户名对应的密码
ABOR: 异常中断数据连接程序
QUIT: 从系统注销
REIN: 重新初始化
2) 文件管理命令
CWD: 改变服务器上的工作目录到指定目录
CDUP: 改变服务器上的工作目录到父目录
DELE: 请求删除服务器上的文件。
LIST: 列出子目录或文件
MKD: 请求在服务器上新建一个目录
PWD: 显示当前工作目录
RMD: 从服务器上删除指定目录
3) 数据格式化命令
TYPE: 定义文件类型,共有四种类型,所带参数也有四种:A、E 、I 、L分别对应ASCII,EBCDIC,IMAGB和LOCAL类型。 STRU: 定义数据的组织
MODE: 定义传输方式
4) 端口定义命令
PASV:服务器选择端口,客户端使用这个端口发送主动打开 PORT: 客户端选择端口,服务器使用这个端口创建主动打开
5) 文件传送命令
RETR: 读取文件,文件从服务器端传送到客户端
STOR: 存放文件,文件从客户端传送到服务器端
STAT: 返回文件的状态
ALLOO: 在服务器为文件分配存储空间
6) 杂项命令
HELP: 询问服务器的信息
NOOP: 检查服务器是否工作
SITE: 指定特定场所的命令
SYST: 询问服务器使用的操作系统
客户端发送 FTP 命令后,服务器返回响应码。响应码用三位数字编码表示:
第一个数字定义命令的状态。
1 表示服务器正确接收信息,还未处理。
2 表示服务器已经正确处理信息。
3 表示服务器正确接收信息,正在处理。
4 表示信息暂时错误。
5 表示信息永久错误。
第二个数字是响应类型的分类。
0 表示语法。
1 表示系统状态和信息。
2 表示连接状态。
3 表示与用户认证有关的信息。
4 表示未指明。
5 表示与文件系统有关的信息。
第三个数字提供了更加附加信息。
介绍完FTP协议后,来看看该软件完成后的效果图
? 客户端的主界面如上图所示,主要是分为以下几个界面:
? 数据输入界面:用来让用户输入服务器的地址,用户名,密码,端口号等。 ? 站点菜单、本地菜单、远程菜单以及帮助菜单。
? 本地文件信息显示界面:主要是用来显示本地文件列表以及文件详情,以及对文件进行相关操作。
? 远程文件信息显示界面:主要是用来显示远程FTP服务器端文件列表以及文件详情,以及对文件进行相关操作。
? 上传下载队列显示界面:显示正在下载或者上传的文件线程的进度。
下载测试
1、下载前选好要下载到的目的目录以及要下载的文件
2、下载中,进度条显示
3.下载完成
=============================================================
=====================================
作者:欧阳鹏 欢迎转载,与人分享是进步的源泉! 下面展示一下上传功能的过程
1、上传前
上传前选择好要将文件或文件夹上传到远程FTP服务器的哪个目的目录下。
2、上传中
添加上传任务
上传任务完成进度显示
3、上传完成
首先看一下该软件的整体代码框架
1、首先介绍程序的主入口FTPMain.java,采用了一个漂亮的外观风格
?
?
?
?
?
?
?
?
? package com.oyp.ftp; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.UIManager; import com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel;
?? public class FTPMain {
?? /**
?? * 本应用的程序入口
?? */
?? public static void main(String args[]) {
?? //导致 runnable 的 run 方法在 EventQueue 的指派线程上被调用。 ?? java.awt.EventQueue.invokeLater(new Runnable() {
?? public void run() {
?? try {
?? //使用 LookAndFeel 对象设置当前的默认外观。
?? UIManager.setLookAndFeel(new NimbusLookAndFeel());//设置一个非常漂亮的外观
?? //
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
?? FTPClientFrame client_Frame = new FTPClientFrame(); ?? client_Frame.setVisible(true);
?? } catch (Exception ex) {
?? Logger.getLogger(FTPClientFrame.class.getName()).log( ?? Level.SEVERE, null, ex);
?? }
?? }
?? });
?? }
?? }
2、介绍界面的主程序代码FTPClientFrame.java
?? package com.oyp.ftp;
??
?? import java.awt.AWTException;
?? import java.awt.MenuItem;
?? import java.awt.PopupMenu;
?? import java.awt.SystemTray;
?? import java.awt.TrayIcon;
?? import java.awt.event.ActionEvent;
?? import java.awt.event.ActionListener;
?? import java.awt.event.WindowEvent;
??
?? import javax.swing.ImageIcon;
?? import javax.swing.JButton;
?? import javax.swing.JFrame;
?? import javax.swing.JLabel;
?? import javax.swing.JMenu;
?? import javax.swing.JMenuBar;
?? import javax.swing.JMenuItem;
?? import javax.swing.JPanel;
?? import javax.swing.JPasswordField;
?? import javax.swing.JSeparator;
?? import javax.swing.JSplitPane;
?? import javax.swing.JTabbedPane;
?? import javax.swing.JTextField;
?? import javax.swing.JToggleButton;
?? import javax.swing.JToolBar;
?? import javax.swing.UIManager;
??
?? import com.oyp.ftp.panel.ftp.FtpPanel;
?? import com.oyp.ftp.panel.local.LocalPanel;
?? import com.oyp.ftp.panel.manager.FtpSiteDialog;
?? import com.oyp.ftp.panel.queue.DownloadPanel;
?? import com.oyp.ftp.panel.queue.QueuePanel;
?? import com.oyp.ftp.panel.queue.UploadPanel;
?? import com.oyp.ftp.utils.FtpClient;
?? import com.oyp.ftp.utils.SiteInfoBean;
?? import com.sun.java.swing.plaf.nimbus.*;
??
?? public class FTPClientFrame extends javax.swing.JFrame {
?? FtpClient ftpClient;
?? private JPasswordField PassField;
?? private JButton cutLinkButton;
?? FtpPanel ftpPanel;
?? LocalPanel localPanel;
?? private JTextField portTextField;
?? private JTextField serverTextField;
?? private JTextField userTextField;
?? private QueuePanel queuePanel;
?? private UploadPanel uploadPanel;
?? private DownloadPanel downloadPanel;
?? private JSplitPane jSplitPane1;
?? private JButton linkButton;
?? private final LinkToAction LINK_TO_ACTION; // 连接到 按钮的动作处理器 ?? private final CutLinkAction CUT_LINK_ACTION; // 断开 按钮的动作处理器 ?? private SystemTray systemTray;
?? private JToggleButton shutdownButton;
?? private final ImageIcon icon = new ImageIcon(getClass().getResource( ?? "/com/oyp/ftp/res/trayIcon.png"));
??
?? public FTPClientFrame() {
?? LINK_TO_ACTION = new LinkToAction(this, "连接到", null); ?? CUT_LINK_ACTION = new CutLinkAction(this, "断开", null);
?? initComponents();
?? initSystemTray();
?? }
??
?? /**
?? * 初始化系统托盘的方法
??? */
??? private void initSystemTray() {
??? if (SystemTray.isSupported())
??? systemTray = SystemTray.getSystemTray();
??? TrayIcon trayIcon = new TrayIcon(icon.getImage());
??? PopupMenu popupMenu = new PopupMenu("托盘菜单");
???
??? // 创建显示主窗体菜单项
??? MenuItem showMenuItem = new MenuItem("显示主窗体");
??? showMenuItem.addActionListener(new ActionListener() { ??? @Override
??? public void actionPerformed(ActionEvent e) {
??? FTPClientFrame.this.setExtendedState(JFrame.NORMAL); ??? FTPClientFrame.this.setVisible(true);
??? }
??? });
???
??? // 创建退出菜单项
??? MenuItem exitMenuItem = new MenuItem("退出");
??? exitMenuItem.addActionListener(new ActionListener() { ??? @Override
??? public void actionPerformed(ActionEvent e) {
??? System.exit(0);
??? }
??? });
???
??? popupMenu.add(showMenuItem);
??? popupMenu.addSeparator();
??? popupMenu.add(exitMenuItem);
??? trayIcon.setPopupMenu(popupMenu);
??? try {
??? systemTray.add(trayIcon);
??? } catch (AWTException e) {
??? e.printStackTrace();
??? }
??? }
???
??? /**
??? * 初始化程序界面的方法
??? */
??? private void initComponents() {
??? setIconImage(icon.getImage());
??? java.awt.GridBagConstraints gridBagConstraints;
???
??? JPanel jPanel1 = new JPanel();
??? JToolBar jToolBar1 = new JToolBar();
??? JButton linkTo = new JButton();
??? cutLinkButton = new JButton();
??? JPanel jPanel4 = new JPanel();
??? JLabel jLabel1 = new JLabel();
??? serverTextField = new JTextField();
??? JLabel jLabel2 = new JLabel();
??? userTextField = new JTextField();
??? JLabel jLabel3 = new JLabel();
??? PassField = new JPasswordField();
??? JLabel jLabel6 = new JLabel();
??? portTextField = new JTextField();
??? linkButton = new JButton();
??? JSplitPane jSplitPane2 = new JSplitPane();
??? jSplitPane1 = new JSplitPane();
??? ftpPanel = new FtpPanel(this); // 初始化FTP远程资源面板
??? localPanel = new LocalPanel(this); // 初始化本地资源管理面板 ??? uploadPanel = new UploadPanel(); // 初始化上传队列面板
??? downloadPanel = new DownloadPanel(); // 初始化下载队列面板 ??? queuePanel = new QueuePanel(this); // 初始化队列面板
???
??? JTabbedPane jTabbedPane1 = new JTabbedPane();
??? JMenuBar MenuBar = new JMenuBar();
??? JMenu fileMenu = new JMenu();
??? JMenuItem ftpManageMenuItem = new JMenuItem();
??? JSeparator jSeparator1 = new JSeparator();
??? JMenuItem linkToMenuItem = new javax.swing.JMenuItem(); ??? JMenuItem cutMenuItem = new javax.swing.JMenuItem(); ??? JSeparator jSeparator2 = new javax.swing.JSeparator(); ??? JMenuItem exitMenuItem = new javax.swing.JMenuItem(); ??? JMenuItem uploadMenuItem = new javax.swing.JMenuItem(); ??? JSeparator jSeparator3 = new javax.swing.JSeparator();
??? JMenuItem createFolderMenuItem = new javax.swing.JMenuItem(); ??? JMenuItem renameMenuItem = new javax.swing.JMenuItem(); ??? JMenuItem delMenuItem = new javax.swing.JMenuItem(); ??? JMenu ftpMenu = new javax.swing.JMenu();
??? JMenuItem downMenuItem = new javax.swing.JMenuItem();
??? JSeparator jSeparator6 = new javax.swing.JSeparator();
??? JMenuItem ftpDelMenuItem = new javax.swing.JMenuItem();
??? JMenuItem ftpRenameMenuItem = new javax.swing.JMenuItem();
??? JMenuItem newFolderMenuItem = new javax.swing.JMenuItem();
??? JMenu helpMenu = new javax.swing.JMenu();
??? JMenuItem aboutMenuItem = new javax.swing.JMenuItem();
??? JMenuItem bugMenuItem = new javax.swing.JMenuItem();
???
??? // setTitle("基于Socket的FTP软件Java实现");
??? setTitle("Java语言实现简单FTP软件__欧阳鹏设计");
??? addWindowListener(new java.awt.event.WindowAdapter() {
??? public void windowOpened(java.awt.event.WindowEvent evt) { ??? formWindowOpened(evt);
??? }
???
??? public void windowIconified(final WindowEvent e) {
??? setVisible(false);
??? }
??? });
??? addComponentListener(new java.awt.event.ComponentAdapter() {
??? public void componentResized(java.awt.event.ComponentEvent evt) { ??? formComponentResized(evt);
??? }
??? });
??? getContentPane().setLayout(new java.awt.GridBagLayout());
???
??? jPanel1.setLayout(new java.awt.GridLayout(0, 1));
???
??? jToolBar1.setRollover(true);
??? jToolBar1.setFloatable(false);
???
??? linkTo.setText("连接到");
??? linkTo.setFocusable(false);
??? linkTo.setAction(LINK_TO_ACTION);
??? jToolBar1.add(linkTo);
???
??? cutLinkButton.setText("断开");
??? cutLinkButton.setEnabled(false);
??? cutLinkButton.setFocusable(false);
??? cutLinkButton.setAction(CUT_LINK_ACTION);
??? jToolBar1.add(cutLinkButton);
???
??? jPanel1.add(jToolBar1);
???
??? shutdownButton = new JToggleButton();
??? shutdownButton.setText("自动关机");
??? shutdownButton.setToolTipText("队列完成后,自动关闭计算机");
??? shutdownButton.setFocusable(false);
??? jToolBar1.add(shutdownButton);
???
??? jPanel4.setBorder(javax.swing.BorderFactory.createEtchedBorder()); ??? jPanel4.setLayout(new javax.swing.BoxLayout(jPanel4,
??? javax.swing.BoxLayout.LINE_AXIS));
???
??? jLabel1.setText("主机地址:");
??? jPanel4.add(jLabel1);
???
??? serverTextField.setText("192.168.1.100");
??? serverTextField.addKeyListener(new java.awt.event.KeyAdapter() { ??? public void keyPressed(java.awt.event.KeyEvent evt) {
??? LinkFTPKeyPressed(evt);
??? }
??? });
??? jPanel4.add(serverTextField);
???
??? jLabel2.setText("用户名:");
??? jPanel4.add(jLabel2);
???
??? userTextField.setText("oyp");
??? userTextField.setMaximumSize(new java.awt.Dimension(200, 2147483647)); ??? userTextField.setPreferredSize(new java.awt.Dimension(100, 21)); ??? userTextField.addKeyListener(new java.awt.event.KeyAdapter() { ??? public void keyPressed(java.awt.event.KeyEvent evt) {
??? LinkFTPKeyPressed(evt);
??? }
??? });
??? jPanel4.add(userTextField);
???
??? jLabel3.setText("密码:");
??? jPanel4.add(jLabel3);
???
??? PassField.setText("oyp");
??? PassField.setMaximumSize(new java.awt.Dimension(200, 2147483647)); ??? PassField.setPreferredSize(new java.awt.Dimension(100, 21));
??? PassField.addKeyListener(new java.awt.event.KeyAdapter() {
??? public void keyPressed(java.awt.event.KeyEvent evt) {
??? LinkFTPKeyPressed(evt);
??? }
??? });
??? jPanel4.add(PassField);
???
??? jLabel6.setText("端口:");
??? jPanel4.add(jLabel6);
???
??? portTextField.setText("21");
??? portTextField.setMaximumSize(new java.awt.Dimension(100, 2147483647)); ??? portTextField.setPreferredSize(new java.awt.Dimension(50, 21)); ??? portTextField.addKeyListener(new java.awt.event.KeyAdapter() { ??? public void keyPressed(java.awt.event.KeyEvent evt) {
??? LinkFTPKeyPressed(evt);
??? }
??? });
??? jPanel4.add(portTextField);
???
??? linkButton.setText("连接");
??? linkButton.setFocusable(false);
???
linkButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); ???
linkButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
??? linkButton.addActionListener(new java.awt.event.ActionListener() { ??? public void actionPerformed(java.awt.event.ActionEvent evt) { ??? linkButtonActionPerformed(evt);
??? }
??? });
??? jPanel4.add(linkButton);
???
??? jPanel1.add(jPanel4);
???
??? gridBagConstraints = new java.awt.GridBagConstraints();
??? gridBagConstraints.gridx = 0; //指定包含组件的显示区域开始边的单元格,其中行的第一个单元格为 gridx=0。
??? gridBagConstraints.gridy = 0; //指定位于组件显示区域的顶部的单元格,其中最上边的单元格为 gridy=0。
??? //当组件的显示区域大于它所请求的显示区域的大小时使用此字段。
??? gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; //在水平方向而不是垂直方向上调整组件大小。
??? gridBagConstraints.weightx = 1.0; //指定如何分布额外的水平空间。 ??? getContentPane().add(jPanel1, gridBagConstraints);
???
??? jSplitPane2.setBorder(null);
??? jSplitPane2.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);
??? jSplitPane2.setResizeWeight(1.0);
??? jSplitPane2.setContinuousLayout(true);
???
??? jSplitPane1.setDividerLocation(400);
??? jSplitPane1.setDividerSize(10);
??? jSplitPane1.setOneTouchExpandable(true);
??? jSplitPane1.setRightComponent(ftpPanel);
??? jSplitPane1.setLeftComponent(localPanel);
???
??? jSplitPane2.setLeftComponent(jSplitPane1);
???
??? jTabbedPane1.setMinimumSize(new java.awt.Dimension(40, 170)); ???
??? jTabbedPane1.addTab("队列", queuePanel);// 添加队列面板
??? jTabbedPane1.addTab("上传队列", uploadPanel);// 添加上传面板
??? jTabbedPane1.addTab("下载队列", downloadPanel);// 添加下载面板
???
??? jSplitPane2.setBottomComponent(jTabbedPane1);
???
??? gridBagConstraints = new java.awt.GridBagConstraints();
??? gridBagConstraints.gridx = 0;
??? gridBagConstraints.gridy = 1;
??? gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; //在水平方向和垂直方向上同时调整组件大小。
??? gridBagConstraints.weightx = 1.0; //指定如何分布额外的水平空间。 ??? gridBagConstraints.weighty = 1.0; //指定如何分布额外的垂直空间。 ??? getContentPane().add(jSplitPane2, gridBagConstraints);
???
??? fileMenu.setMnemonic('f');
??? fileMenu.setText("站点(F)");
???
??? ftpManageMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke( ??? java.awt.event.KeyEvent.VK_S,
??? java.awt.event.InputEvent.CTRL_MASK));
??? ftpManageMenuItem.setText("FTP站点管理(S)");
??? ftpManageMenuItem.addActionListener(new ActionListener() {
??? @Override
??? public void actionPerformed(ActionEvent e) {
??? // System.out.println("action");
??? FtpSiteDialog dialog = new FtpSiteDialog(FTPClientFrame.this); ??? dialog.setVisible(true);
??? }
??? });
??? fileMenu.add(ftpManageMenuItem);
??? fileMenu.add(jSeparator1);
???
??? linkToMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke( ??? java.awt.event.KeyEvent.VK_C,
??? java.awt.event.InputEvent.CTRL_MASK));
??? linkToMenuItem.setText("连接到...(C)");
??? linkToMenuItem.setAction(LINK_TO_ACTION);
??? fileMenu.add(linkToMenuItem);
???
??? cutMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke( ??? java.awt.event.KeyEvent.VK_Z,
??? java.awt.event.InputEvent.CTRL_MASK));
??? cutMenuItem.setText("断开(Z)");
??? cutMenuItem.setAction(CUT_LINK_ACTION);
??? fileMenu.add(cutMenuItem);
??? fileMenu.add(jSeparator2);
???
??? exitMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke( ??? java.awt.event.KeyEvent.VK_X,
??? java.awt.event.InputEvent.CTRL_MASK));
??? exitMenuItem.setText("退出(X)");
??? exitMenuItem.addActionListener(new ActionListener() {
??? @Override
??? public void actionPerformed(ActionEvent e) {
??? System.exit(0);
??? }
??? });
??? fileMenu.add(exitMenuItem);
???
??? MenuBar.add(fileMenu);
???
??? JMenu localMenu = new JMenu();
??? localMenu.setMnemonic('l');
??? localMenu.setText("本地(L)");
???
??? uploadMenuItem.setMnemonic('U');
??? uploadMenuItem.setText("上传(U)");
???
uploadMenuItem.setAction(localPanel.getActionMap().get("uploadAction")); ???
??? localMenu.add(uploadMenuItem);
??? localMenu.add(jSeparator3);
???
??? createFolderMenuItem.setMnemonic('C');
??? createFolderMenuItem.setText("新建文件夹(C)");
??? createFolderMenuItem.setAction(localPanel.getActionMap().get( ??? "createFolderAction"));
??? localMenu.add(createFolderMenuItem);
???
??? renameMenuItem.setMnemonic('R');
??? renameMenuItem.setText("重命名(R)");
???
renameMenuItem.setAction(localPanel.getActionMap().get("renameAction")); ??? localMenu.add(renameMenuItem);
???
??? delMenuItem.setMnemonic('D');
??? delMenuItem.setText("删除(D)");
??? delMenuItem.setAction(localPanel.getActionMap().get("delAction")); ??? localMenu.add(delMenuItem);
???
??? JMenuItem localrefreshMenuItem = new JMenuItem();
??? localrefreshMenuItem.setMnemonic('R');
??? localrefreshMenuItem.setText("刷新(R)");
??? localrefreshMenuItem.setAction(localPanel.getActionMap().get( ??? "refreshAction"));
??? localMenu.add(localrefreshMenuItem);
???
??? MenuBar.add(localMenu);
???
??? ftpMenu.setMnemonic('r');
??? ftpMenu.setText("远程(R)");
???
??? downMenuItem.setMnemonic('U');
??? downMenuItem.setText("下载(U)");
??? downMenuItem.setAction(ftpPanel.getActionMap().get("downAction")); ??? ftpMenu.add(downMenuItem);
??? ftpMenu.add(jSeparator6);
???
??? ftpDelMenuItem.setMnemonic('D');
??? ftpDelMenuItem.setText("删除(D)");
??? ftpDelMenuItem.setAction(ftpPanel.getActionMap().get("delAction")); ??? ftpMenu.add(ftpDelMenuItem);
???
??? ftpRenameMenuItem.setMnemonic('R');
??? ftpRenameMenuItem.setText("重命名(R)");
??? ftpRenameMenuItem
??? .setAction(ftpPanel.getActionMap().get("renameAction")); ??? ftpMenu.add(ftpRenameMenuItem);
???
??? newFolderMenuItem.setMnemonic('C');
??? newFolderMenuItem.setText("新建文件夹(C)");
??? newFolderMenuItem.setAction(ftpPanel.getActionMap().get(
??? "createFolderAction"));
??? ftpMenu.add(newFolderMenuItem);
???
??? JMenuItem refreshMenuItem = new JMenuItem();
??? refreshMenuItem.setMnemonic('R');
??? refreshMenuItem.setText("刷新(R)");
???
refreshMenuItem.setAction(ftpPanel.getActionMap().get("refreshAction")); ??? ftpMenu.add(refreshMenuItem);
???
??? MenuBar.add(ftpMenu);
???
??? helpMenu.setText("帮助(H)");
??? aboutMenuItem.setMnemonic('a');
??? aboutMenuItem.setText("关于(A)");
??? aboutMenuItem.addActionListener(new AboutItemAction(this));
??? helpMenu.add(aboutMenuItem);
???
??? bugMenuItem.setMnemonic('u');
??? bugMenuItem.setText("错误报告(U)");
??? bugMenuItem.addActionListener(new BugItemAction());
??? helpMenu.add(bugMenuItem);
???
??? MenuBar.add(helpMenu);
???
??? setJMenuBar(MenuBar);
???
??? java.awt.Dimension screenSize = java.awt.Toolkit.getDefaultToolkit() ??? .getScreenSize();
??? setBounds((screenSize.width - 800) / 2, (screenSize.height - 600) / 2, ??? 800, 700);
??? }
???
??? public JToggleButton getShutdownButton() {
??? return shutdownButton;
??? }
???
??? /**
??? * 窗体装载的事件处理方法
??? */
??? private void formWindowOpened(java.awt.event.WindowEvent evt) { ??? jSplitPane1.setDividerLocation(0.50);
??? localPanel.getLocalDiskComboBox().setSelectedIndex(1);
??? localPanel.getLocalDiskComboBox().setSelectedIndex(0);
??? }
???
??? /**
??? * 窗体大小调整的事件处理方法
??? */
??? private void formComponentResized(java.awt.event.ComponentEvent evt) { ??? jSplitPane1.setDividerLocation(0.50);
??? }
???
??? /**
??? * 连接按钮的事件处理方法
??? */
??? private void linkButtonActionPerformed(java.awt.event.ActionEvent evt) { ??? try {
??? String server = serverTextField.getText(); // 获取服务器地址 ??? if (server == null) {
??? return;
??? }
??? String portStr = portTextField.getText(); // 获取端口号
??? if (portStr == null) {
??? portStr = "21";
??? }
??? int port = Integer.parseInt(portStr.trim());
??? String userStr = userTextField.getText(); // 获取用户名
??? userStr = userStr == null ? "" : userStr.trim();
??? String passStr = PassField.getText(); // 获取密码
??? passStr = passStr == null ? "" : passStr.trim();
??? cutLinkButton.doClick();
??? ftpClient = new FtpClient();
??? ftpClient.openServer(server.trim(), port); // 连接服务器
??? ftpClient.login(userStr, passStr); // 登录服务器
??? ftpClient.binary(); // 使用二进制传输模式
??? if (ftpClient.serverIsOpen()) { // 如果连接成功
??? CUT_LINK_ACTION.setEnabled(true); // 设置断开按钮可用
??? } else { // 否则
??? CUT_LINK_ACTION.setEnabled(false); // 设置断开按钮不可用 ??? return; // 并结束事件处理
??? }
??? // 设置本地资源管理面板的FTP连接信息
??? localPanel.setFtpClient(server, port, userStr, passStr);
??? // 设置上传按钮可用
??? localPanel.getActionMap().get("uploadAction").setEnabled(true); ??? ftpPanel.setFtpClient(ftpClient);// 设置FTP资源管理面板的FTP连接信息
??? // 设置下载按钮可用
??? ftpPanel.getActionMap().get("downAction").setEnabled(true);
??? ftpPanel.refreshCurrentFolder();// 刷新FTP资源管理面板的当前文件夹 ??? queuePanel.startQueue(); // 启动任务队列线程
??? } catch (Exception ex) {
??? ex.printStackTrace();
??? }
??? }
???
??? /**
??? * 连接FTP相关的文本框 和密码框的回车事件
??? */
??? private void LinkFTPKeyPressed(java.awt.event.KeyEvent evt) {
??? if (evt.getKeyChar() == '\n') {
??? linkButton.doClick();
??? }
??? }
???
??? public LocalPanel getLocalPanel() {
??? return localPanel;
??? }
???
??? public FtpPanel getFtpPanel() {
??? return ftpPanel;
??? }
???
??? public QueuePanel getQueuePanel() {
??? return queuePanel;
??? }
???
??? public UploadPanel getUploadPanel() {
??? return uploadPanel;
??? }
???
??? public DownloadPanel getDownloadPanel() {
??? return downloadPanel;
??? }
???
??? public FtpClient getFtpClient() {
??? return ftpClient;
??? }
???
??? /**
??? * 设置FTP连接信息的方法,由FTP站点管理器调用
??? */
??? public void setLinkInfo(SiteInfoBean bean) {
??? serverTextField.setText(bean.getServer()); // 设置主机地址 ??? portTextField.setText(bean.getPort() + ""); // 设置端口号 ??? userTextField.setText(bean.getUserName()); // 设置用户名 ??? PassField.setText(""); // 密码清空
??? PassField.requestFocus(); // 密码框请求焦点
??? }
??? }
1、首先看一下本地窗口的布局效果
2、看一下本地窗口实现的代码框架
2、本地窗口的具体实现代码LocalPanel.java
?
? package com.oyp.ftp.panel.local;
?
?
?
?
?
?
? import java.awt.Color; import java.awt.Desktop; import java.awt.Dimension; import java.awt.event.ItemEvent; import java.io.File; import java.io.IOException; import java.util.Date;
?? import java.util.LinkedList;
?? import java.util.Queue;
?? import java.util.logging.Level;
?? import java.util.logging.Logger;
??
?? import javax.swing.ActionMap;
?? import javax.swing.DefaultComboBoxModel;
?? import javax.swing.JButton;
?? import javax.swing.JOptionPane;
?? import javax.swing.SwingUtilities;
?? import javax.swing.table.DefaultTableModel;
?? import javax.swing.table.TableModel;
?? import javax.swing.table.TableRowSorter;
?? import javax.swing.table.TableStringConverter; ??
?? import com.oyp.ftp.FTPClientFrame;
?? import com.oyp.ftp.panel.FTPTableCellRanderer; ?? import com.oyp.ftp.panel.ftp.TableConverter;
?? import com.oyp.ftp.utils.DiskFile;
?? public class LocalPanel extends javax.swing.JPanel { ??
?? Queue<Object[]> queue = new LinkedList<Object[]>(); ?? private UploadThread uploadThread = null;
?? private Desktop desktop = null;
?? private javax.swing.JButton createFolderButton; ?? private javax.swing.JButton delButton;
?? private javax.swing.JScrollPane scrollPane;
?? private javax.swing.JToolBar.Separator jSeparator1; ?? private javax.swing.JToolBar toolBar;
?? private javax.swing.JComboBox localDiskComboBox; ?? javax.swing.JTable localDiskTable;
?? javax.swing.JLabel localSelFilePathLabel;
?? private javax.swing.JButton renameButton;
?? private javax.swing.JButton uploadButton;
?? private TableRowSorter<TableModel> sorter; ?? FTPClientFrame frame = null;
??
?? public LocalPanel() {
?? initComponents();
?? }
??
?? public LocalPanel(FTPClientFrame client_Frame) {
?? frame = client_Frame;
?? if (Desktop.isDesktopSupported()) {
?? desktop = Desktop.getDesktop();
?? }
?? initComponents();
?? }
??
?? /**
?? * 界面布局与初始化方法
?? */
?? private void initComponents() {
?? ActionMap actionMap = getActionMap();
?? actionMap.put("delAction", new DelFileAction(this, "删除", null));
?? actionMap.put("renameAction", new RennameAction(this, "重命名", null)); ?? actionMap.put("createFolderAction", new CreateFolderAction(this, ?? "新建文件夹", null));
?? actionMap.put("uploadAction", new UploadAction(this, "上传", null)); ?? actionMap.put("refreshAction", new RefreshAction(this, "刷新", null)); ??
?? java.awt.GridBagConstraints gridBagConstraints;
??
?? toolBar = new javax.swing.JToolBar();
?? delButton = new javax.swing.JButton();
?? renameButton = new javax.swing.JButton();
?? createFolderButton = new javax.swing.JButton();
?? uploadButton = new javax.swing.JButton();
?? jSeparator1 = new javax.swing.JToolBar.Separator();
?? localDiskComboBox = new javax.swing.JComboBox();
?? localDiskComboBox.setPreferredSize(new Dimension(100, 25));
?? scrollPane = new javax.swing.JScrollPane();
?? localDiskTable = new javax.swing.JTable();
?? localDiskTable.setDragEnabled(true);
?? localSelFilePathLabel = new javax.swing.JLabel();
?? /**
?? * 向现有边框添加一个标题,使其具有指定的位置和默认字体和文本颜色(由当前外观确定)。
?? * TitledBorder.CENTER: 将标题文本置于边框线的中心。
?? * TitledBorder.ABOVE_TOP: 将标题置于边框顶端线的上部。
?? */
?? setBorder(javax.swing.BorderFactory.createTitledBorder(null, "本地", ?? javax.swing.border.TitledBorder.CENTER,
?? javax.swing.border.TitledBorder.ABOVE_TOP));
?? setLayout(new java.awt.GridBagLayout());
??
?? toolBar.setRollover(true);
?? toolBar.setFloatable(false);
??
?? delButton.setText("删除");
?? delButton.setFocusable(false);
??? delButton.setAction(actionMap.get("delAction"));
??? toolBar.add(delButton);
???
??? renameButton.setText("重命名");
??? renameButton.setFocusable(false);
??? renameButton.setAction(actionMap.get("renameAction"));
??? toolBar.add(renameButton);
???
??? createFolderButton.setText("新文件夹");
??? createFolderButton.setFocusable(false);
??? createFolderButton.setAction(actionMap.get("createFolderAction")); ??? toolBar.add(createFolderButton);
???
??? uploadButton.setText("上传");
??? uploadButton.setFocusable(false);
??? uploadButton.setAction(actionMap.get("uploadAction"));
??? toolBar.add(uploadButton);
???
??? JButton refreshButton = new JButton();
??? refreshButton.setText("刷新");
??? refreshButton.setFocusable(false);
??? refreshButton.setAction(actionMap.get("refreshAction"));
??? toolBar.add(refreshButton);
??? toolBar.add(jSeparator1);
???
??? //File.listRoots():列出可用的文件系统根。
??? localDiskComboBox.setModel(new
DefaultComboBoxModel(File.listRoots()));
??? localDiskComboBox.addItemListener(new java.awt.event.ItemListener() { ??? public void itemStateChanged(java.awt.event.ItemEvent evt) { ??? localDiskComboBoxItemStateChanged(evt);
??? }
??? });
??? toolBar.add(localDiskComboBox);
???
??? gridBagConstraints = new java.awt.GridBagConstraints();
??? gridBagConstraints.gridx = 0;
??? gridBagConstraints.gridy = 1;
??? gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; ??? gridBagConstraints.weightx = 1.0;
??? add(toolBar, gridBagConstraints);
??? localDiskTable.setModel(new LocalTableModel());
??? localDiskTable.setShowHorizontalLines(false);
??? localDiskTable.setShowVerticalLines(false);
??? localDiskTable.getTableHeader().setReorderingAllowed(false);
??? localDiskTable.addMouseListener(new java.awt.event.MouseAdapter() { ??? public void mouseClicked(java.awt.event.MouseEvent evt) { ??? localDiskTableMouseClicked(evt);
??? }
??? });
??? scrollPane.setViewportView(localDiskTable);
??? scrollPane.getViewport().setBackground(Color.WHITE);
??? //设置渲染本地资源和FTP资源表格组件的渲染器
??? localDiskTable.getColumnModel().getColumn(0).setCellRenderer( ??? FTPTableCellRanderer.getCellRanderer());
??? //RowSorter 的一个实现,它使用 TableModel 提供排序和过滤操作。
??? sorter = new TableRowSorter<TableModel>(localDiskTable.getModel()); ??? TableStringConverter converter = new TableConverter();
??? //设置负责将值从模型转换为字符串的对象。
??? sorter.setStringConverter(converter);
??? //设置 RowSorter。RowSorter 用于提供对 JTable 的排序和过滤。
??? localDiskTable.setRowSorter(sorter);
??? sorter.toggleSortOrder(0);
???
??? gridBagConstraints = new java.awt.GridBagConstraints();
??? gridBagConstraints.gridx = 0;
??? gridBagConstraints.gridy = 2;
??? gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; ??? gridBagConstraints.weightx = 1.0;
??? gridBagConstraints.weighty = 1.0;
??? add(scrollPane, gridBagConstraints);
???
??? localSelFilePathLabel.setBorder(javax.swing.BorderFactory
??? .createEtchedBorder());
??? gridBagConstraints = new java.awt.GridBagConstraints();
??? gridBagConstraints.gridx = 0;
??? gridBagConstraints.gridy = 3;
??? gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
??? add(localSelFilePathLabel, gridBagConstraints);
??? }
???
??? /**
??? * 本地磁盘下拉选择框的选项改变事件处理方法,由事件监听器调用
??? */
??? private void localDiskComboBoxItemStateChanged(java.awt.event.ItemEvent evt) {
??? if (evt.getStateChange() == ItemEvent.SELECTED) {
??? Object item = evt.getItem(); // 获取选择的下拉列表的选项
??? if (item instanceof File) { // 如果该选项是File类的实例对象 ??? File selDisk = (File) item; // 将该选项转换成File类
??? // 调用listLocalFiles()方法,显示该File类指定的磁盘文件列表 ??? listLocalFiles(selDisk);
??? }
??? }
??? }
???
??? /**
??? * 刷新指定文件夹的方法
??? */
??? void refreshFolder(File file) {
??? listLocalFiles(file);
??? }
???
??? /**
??? * 刷新本地当前文件夹的方法
??? */
??? public void refreshCurrentFolder() {
??? final File file = getCurrentFolder(); // 获取当前文件夹
??? Runnable runnable = new Runnable() { // 创建新的线程
??? public void run() {
??? listLocalFiles(file); // 重载当前文件夹的列表到表格中 ??? }
??? };
??? //导致 runnable 的 run 方法在 EventQueue 的指派线程上被调用。
??? SwingUtilities.invokeLater(runnable); // 在事件线程中调用该线程对象 ??? }
???
??? /**
??? * 获取当前文件夹
??? */
??? public File getCurrentFolder() {
??? // 使用路径标签的路径创建当前文件夹对象
??? File file = new File(localSelFilePathLabel.getText());
??? // 如果表格选择了文件夹,或选择的文件有真是的上级文件夹
??? if (localDiskTable.getSelectedRow() > 1 && file.getParentFile() != null) ??? file = file.getParentFile(); // 获取该上级文件夹
??? return file; // 返回文件夹对象
??? }
???
??? /**
??? * 本地磁盘文件的表格单击和双击事件处理方法
??? */
??? private void localDiskTableMouseClicked(java.awt.event.MouseEvent evt) { ??? int selectedRow = localDiskTable.getSelectedRow(); // 获取选择的表格行号 ??? if (selectedRow < 0)
??? return;
??? // 获取表格中选择的当前行的第一个字段的值
??? Object value = localDiskTable.getValueAt(selectedRow, 0);
??? if (value instanceof DiskFile) { // 如果该值是DiskFile的实例对象 ??? DiskFile selFile = (DiskFile) value;
??? // 设置状态栏的本地文件路径
??? localSelFilePathLabel.setText(selFile.getAbsolutePath()); ??? if (evt.getClickCount() >= 2) { // 如果是双击鼠标
??? if (selFile.isDirectory()) { // 并且选择的是文件夹
??? listLocalFiles(selFile); // 显示该文件夹的内容列表
??? } else if (desktop != null) { // 如果不是文件夹
??? try {
??? desktop.open(selFile); // 关联本地系统程序打开该文件 ??? } catch (IOException ex) {
??? Logger.getLogger(FTPClientFrame.class.getName()).log( ??? Level.SEVERE, null, ex);
??? }
??? }
??? }
??? } else { // 如果选择的表格内容不是DiskFile类的实例
??? // 判断选择的是不是..选项
??? if (evt.getClickCount() >= 2 && value.equals("..")) {
??? // 创建当前选择文件的临时文件
??? File tempFile = new File((localSelFilePathLabel.getText())); ??? // 显示选择的文件的上级目录列表
??? listLocalFiles(tempFile.getParentFile());
??? }
??? }
??? }
???
??? /**
??? * 读取本地文件到表格的方法
??? */
??? private void listLocalFiles(File selDisk) {
??? if (selDisk == null || selDisk.isFile()) {
??? return;
??? }
??? localSelFilePathLabel.setText(selDisk.getAbsolutePath());
??? File[] listFiles = selDisk.listFiles(); // 获取磁盘文件列表
??? // 获取表格的数据模型
??? DefaultTableModel model = (DefaultTableModel)
localDiskTable.getModel();
??? model.setRowCount(0); // 清除模型的内容
??? model.addRow(new Object[] { ".", "<DIR>", "" }); // 创建.选项
??? model.addRow(new Object[] { "..", "<DIR>", "" }); // 创建..选项 ??? if (listFiles == null) {
??? JOptionPane.showMessageDialog(this, "该磁盘无法访问");
??? return;
??? }
??? // 遍历磁盘根文件夹的内容,添加到表格中
??? for (File file : listFiles) {
??? File diskFile = new DiskFile(file); // 创建文件对象
??? String length = file.length() + "B "; // 获取文件大小
??? if (file.length() > 1000 * 1000 * 1000) { // 计算文件G单位 ??? length = file.length() / 1000000000 + "G ";
??? }
??? if (file.length() > 1000 * 1000) { // 计算文件M单位
??? length = file.length() / 1000000 + "M ";
??? }
??? if (file.length() > 1000) {
??? length = file.length() / 1000 + "K "; // 计算文件K单位 ??? }
??? if (file.isDirectory()) { // 显示文件夹标志
??? length = "<DIR>";
??? }
??? // 获取文件的最后修改日期
??? String modifDate = new Date(file.lastModified()).toLocaleString(); ??? if (!file.canRead()) {
??? length = "未知";
??? modifDate = "未知";
??? }
??? // 将单个文件的信息添加到表格的数据模型中
??? model.addRow(new Object[] { diskFile, length, modifDate }); ??? }
??? localDiskTable.clearSelection(); // 取消表格的选择项
??? }
???
??? /**
??? * 停止文件上传线程的方法
??? */
??? public void stopUploadThread() {
??? if (uploadThread != null)
??? uploadThread.stopThread();
??? }
???
??? public javax.swing.JComboBox getLocalDiskComboBox() {
??? return localDiskComboBox;
??? }
???
??? /**
??? * 设置FTP连接,并启动上传队列线程的方法。
??? */
??? public void setFtpClient(String server, int port, String userStr, ??? String passStr) {
??? if (uploadThread != null)
??? uploadThread.stopThread();
??? uploadThread = new UploadThread(this, server, port, userStr, passStr); ??? uploadThread.start();
??? }
???
??? public Queue<Object[]> getQueue() {
??? return queue;
??? }
??? }
1、首先看一下远程窗口的布局效果
2、看一下本地窗口实现的代码框架
3、远程窗口主要实现代码FtpPanel.java
?
?
?
?
?
?
?
?
? package com.oyp.ftp.panel.ftp; import java.awt.Color; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.IOException; import java.util.LinkedList; import java.util.Queue; import java.util.logging.Level;
?? import java.util.logging.Logger;
??
?? import javax.swing.ActionMap;
?? import javax.swing.JScrollPane;
?? import javax.swing.JTable;
?? import javax.swing.SwingUtilities; ?? import javax.swing.Timer;
?? import javax.swing.table.DefaultTableModel; ?? import javax.swing.table.TableModel;
?? import javax.swing.table.TableRowSorter;
?? import javax.swing.table.TableStringConverter;
??
??
?? import sun.net.TelnetInputStream;
?? import com.oyp.ftp.FTPClientFrame;
?? import com.oyp.ftp.panel.FTPTableCellRanderer;
?? import com.oyp.ftp.utils.FtpClient;
?? import com.oyp.ftp.utils.FtpFile;
??
?? public class FtpPanel extends javax.swing.JPanel {
??
?? FtpClient ftpClient;
?? private javax.swing.JButton createFolderButton;
?? private javax.swing.JButton delButton;
?? private javax.swing.JButton downButton;
?? javax.swing.JTable ftpDiskTable;
?? private javax.swing.JLabel ftpSelFilePathLabel;
?? private javax.swing.JScrollPane scrollPane;
?? private javax.swing.JToolBar toolBar;
?? private javax.swing.JButton refreshButton;
?? private javax.swing.JButton renameButton;
?? FTPClientFrame frame = null;
?? Queue<Object[]> queue = new LinkedList<Object[]>();
?? private DownThread thread;
??
?? public FtpPanel() {
?? initComponents();
?? }
??
?? public FtpPanel(FTPClientFrame client_Frame) {
?? frame = client_Frame;
?? initComponents();
?? }
??
?? private void initComponents() {
?? ActionMap actionMap = getActionMap();
?? actionMap.put("createFolderAction", new CreateFolderAction(this, ?? "创建文件夹", null));
?? actionMap.put("delAction", new DelFileAction(this, "删除", null));
?? actionMap.put("refreshAction", new RefreshAction(this, "刷新", null)); ?? actionMap.put("renameAction", new RenameAction(this, "重命名", null)); ?? actionMap.put("downAction", new DownAction(this, "下载", null)); ??
?? java.awt.GridBagConstraints gridBagConstraints;
??
?? toolBar = new javax.swing.JToolBar();
?? delButton = new javax.swing.JButton();
?? renameButton = new javax.swing.JButton();
?? createFolderButton = new javax.swing.JButton();
?? downButton = new javax.swing.JButton();
?? refreshButton = new javax.swing.JButton();
?? scrollPane = new JScrollPane();
?? ftpDiskTable = new JTable();
?? ftpDiskTable.setDragEnabled(true);
?? ftpSelFilePathLabel = new javax.swing.JLabel();
??
?? setBorder(javax.swing.BorderFactory.createTitledBorder(null, "远程", ?? javax.swing.border.TitledBorder.CENTER,
?? javax.swing.border.TitledBorder.ABOVE_TOP));
?? setLayout(new java.awt.GridBagLayout());
??
?? toolBar.setRollover(true);
?? toolBar.setFloatable(false);
??
?? delButton.setText("删除");
?? delButton.setFocusable(false);
??
delButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
?? delButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); ?? delButton.setAction(actionMap.get("delAction"));
?? toolBar.add(delButton);
??
?? renameButton.setText("重命名");
?? renameButton.setFocusable(false);
?? renameButton.setAction(actionMap.get("renameAction"));
?? toolBar.add(renameButton);
??
?? createFolderButton.setText("新文件夹");
?? createFolderButton.setFocusable(false);
?? createFolderButton.setAction(actionMap.get("createFolderAction")); ?? toolBar.add(createFolderButton);
???
??? downButton.setText("下载");
??? downButton.setFocusable(false);
??? downButton.setAction(actionMap.get("downAction"));
??? toolBar.add(downButton);
???
??? refreshButton.setText("刷新");
??? refreshButton.setFocusable(false);
??? refreshButton.setAction(actionMap.get("refreshAction"));
??? toolBar.add(refreshButton);
???
??? gridBagConstraints = new java.awt.GridBagConstraints();
??? gridBagConstraints.gridx = 0;
??? gridBagConstraints.gridy = 0;
??? gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; ??? gridBagConstraints.weightx = 1.0;
??? add(toolBar, gridBagConstraints);
???
??? ftpDiskTable.setModel(new FtpTableModel());
??? ftpDiskTable.setShowHorizontalLines(false);
??? ftpDiskTable.setShowVerticalLines(false);
??? ftpDiskTable.getTableHeader().setReorderingAllowed(false);
??? ftpDiskTable.setDoubleBuffered(true);
??? ftpDiskTable.addMouseListener(new java.awt.event.MouseAdapter() { ??? public void mouseClicked(java.awt.event.MouseEvent evt) { ??? ftpDiskTableMouseClicked(evt);
??? }
??? });
??? scrollPane.setViewportView(ftpDiskTable);
??? scrollPane.getViewport().setBackground(Color.WHITE);
??? //设置渲染本地资源和FTP资源表格组件的渲染器
??? ftpDiskTable.getColumnModel().getColumn(0).setCellRenderer(
??? FTPTableCellRanderer.getCellRanderer());
??? //RowSorter 的一个实现,它使用 TableModel 提供排序和过滤操作。
??? TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>( ??? ftpDiskTable.getModel());
??? TableStringConverter converter = new TableConverter();
??? //设置负责将值从模型转换为字符串的对象。
??? sorter.setStringConverter(converter);
??? //设置 RowSorter。RowSorter 用于提供对 JTable 的排序和过滤。
??? ftpDiskTable.setRowSorter(sorter);
??? /**
??? * 颠倒指定列的排序顺序。调用此方法时,由子类提供具体行为。
??? * 通常,如果指定列已经是主要排序列,则此方法将升序变为降序(或将降序变为升序); ??? * 否则,使指定列成为主要排序列,并使用升序排序顺序。如果指定列不可排序,则此方法没有任何效果。
??? */
??? sorter.toggleSortOrder(0);
???
??? gridBagConstraints = new java.awt.GridBagConstraints();
??? gridBagConstraints.gridx = 0;
??? gridBagConstraints.gridy = 2;
??? gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; ??? gridBagConstraints.weightx = 1.0;
??? gridBagConstraints.weighty = 1.0;
??? add(scrollPane, gridBagConstraints);
???
??? ftpSelFilePathLabel.setBorder(javax.swing.BorderFactory
??? .createEtchedBorder());
??? gridBagConstraints = new java.awt.GridBagConstraints();
??? gridBagConstraints.gridx = 0;
??? gridBagConstraints.gridy = 3;
??? gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; ??? add(ftpSelFilePathLabel, gridBagConstraints);
??? }
???
??? /**
??? * 表格单击或双击事件的处理方法。
??? */
??? private void ftpDiskTableMouseClicked(java.awt.event.MouseEvent evt) { ??? int selectedRow = ftpDiskTable.getSelectedRow();
??? Object value = ftpDiskTable.getValueAt(selectedRow, 0);
??? if (value instanceof FtpFile) {
??? FtpFile selFile = (FtpFile) value;
??? ftpSelFilePathLabel.setText(selFile.getAbsolutePath()); ??? if (evt.getClickCount() >= 2) { //双击鼠标
??? if (selFile.isDirectory()) {
??? try {
??? ftpClient.cd(selFile.getAbsolutePath());
??? listFtpFiles(ftpClient.list());
??? } catch (IOException ex) {
??? ex.printStackTrace();
??? }
??? }
??? }
??? }
??? }
???
??? /**
??? * 读取FTP文件到表格的方法
??? * @param list
??? * 读取FTP服务器资源列表的输入流
??? */
??? public synchronized void listFtpFiles(final TelnetInputStream list) {
??? // 获取表格的数据模型
??? final DefaultTableModel model = (DefaultTableModel) ftpDiskTable ??? .getModel();
??? model.setRowCount(0);
??? // 创建一个线程类
??? Runnable runnable = new Runnable() {
??? public synchronized void run() {
??? ftpDiskTable.clearSelection();
??? try {
??? String pwd = getPwd(); // 获取FTP服务器的当前文件夹
??? model.addRow(new Object[] { new FtpFile(".", pwd, true), ??? "", "" }); // 添加“.”符号
??? model.addRow(new Object[] { new FtpFile("..", pwd, true), ??? "", "" }); // 添加“..”符号
??? /*
??? byte[]names=new byte[2048];
??? int bufsize=0;
??? bufsize=list.read(names, 0, names.length);
??? // list.close();
??? int i=0,j=0;
??? while(i<bufsize){
??? char bc=(char)names[i];
??? System.out.print(i+" "+bc+" ");
??? //文件名在数据中开始做坐标为j,i-j为文件名的长度,文件名在数据中的结束下标为i-1
??? if (names[i]==13) {
??? // System.out.println("j:"+j+" i:"+i+ " i-j:"+(i-j)); ??? String temName=new String(names,j,i-j);
??? System.out.println("temName="+temName);
??? j=i+2;
??? }
??? i=i+1;
??? }
??? */
??? /* 其中格式应满足如下格式的字符串 结果为:
??? 0 -: 1 r: 2 w: 3 x: 4 -: 5 -: 6 -: 7 -: 8 -: 9 -: 10 : 11 1: 12 : 13 u: 14 s: 15 e: 16 r: 17 : 18 g: 19 r: 20 o: 21 u: 22 p: 23 : 24 : 25 : 26 : 27 : 28 : 29 : 30 : 31 : 32 6: 33 7: 34 8: 35 4: 36 3: 37 0: 38 : 39 A: 40 p: 41 r: 42 : 43 1: 44 6: 45 : 46 2: 47 1: 48 :: 49 4: 50 6: 51 : 52 F: 53 T: 54 P: 55 ?: 56 ?: 57 ?: 58 ?: 59 ?: 60 ?: 61 ?: 62 ?: 63 ?: 64 ?: 65 ?: 66 ?: 67 ?: 68 ?: 69 ?: 70 ?: 71 ?: 72 ?: 73 .: 74 p: 75 d: 76 f: 77
???
??? -rwx------ 1 user group 678430 Apr 16 21:46 FTP客户端的设计与实现.pdf
??? -rwx------ 1 user group 87504927 Apr 18 22:50 VC.深入详解(孙鑫)[].pdf
??? -rwx------ 1 user group 57344 Apr 18 05:32 腾讯电商2013实习生招聘TST推荐模板.xls
???
??? *<br>d 表示目录
??? * <br>- 表示文件
??? * <br>rw-rw-rw- 表示权限设置
???
??? dateStr:39-51
??? sizeOrDir:23-38
??? fileName:52-^
??? */
???
???
/*********************************************************/
??? byte[]names=new byte[2048];
??? int bufsize=0;
??? bufsize=list.read(names, 0, names.length);
??? int i=0,j=0;
??? while(i<bufsize){
??? //字符模式为10,二进制模式为13
??? // if (names[i]==10) {
??? if (names[i]==13) {
??? //获取字符串 -rwx------ 1 user group 57344 Apr 18 05:32 腾讯电商2013实习生招聘TST推荐模板.xls
??? //文件名在数据中开始做坐标为j,i-j为文件名的长度,文件名在数据中的结束下标为i-1
??? String fileMessage = new String(names,j,i-j); ??? if(fileMessage.length() == 0){
??? System.out.println("fileMessage.length() == 0"); ??? break;
??? }
??? //按照空格将fileMessage截为数组后获取相关信息 ??? // 正则表达式 \s表示空格,{1,}表示1一个以上 ??? if(!fileMessage.split("\\s+")[8].equals(".") && !fileMessage.split("\\s+")[8].equals("..")){
??? /**文件大小*/
??? String sizeOrDir="";
??? if (fileMessage.startsWith("d")) {//如果是目录 ??? sizeOrDir="<DIR>";
??? }else if (fileMessage.startsWith("-")) {//如果是文件
??? sizeOrDir=fileMessage.split("\\s+")[4];
??? }
??? /**文件名*/
??? String fileName=fileMessage.split("\\s+")[8]; ??? /**文件日期*/
??? String dateStr =fileMessage.split("\\s+")[5] +" "+fileMessage.split("\\s+")[6]+" " +fileMessage.split("\\s+")[7];
??? // System.out.println("sizeOrDir="+sizeOrDir); ??? // System.out.println("fileName="+fileName); ??? // System.out.println("dateStr="+dateStr); ???
??? FtpFile ftpFile = new FtpFile();
??? // 将FTP目录信息初始化到FTP文件对象中
??? ftpFile.setLastDate(dateStr);
??? ftpFile.setSize(sizeOrDir);
??? ftpFile.setName(fileName);
??? ftpFile.setPath(pwd);
??? // 将文件信息添加到表格中
??? model.addRow(new Object[] { ftpFile,
ftpFile.getSize(),
??? dateStr });
??? }
???
??? // j=i+1;//上一次位置为字符模式
??? j=i+2;//上一次位置为二进制模式
??? }
??? i=i+1;
??? }
??? list.close();
???
???
/**********************************************************************
??? //下面的方法太死了,不够灵活
??? BufferedReader br = new BufferedReader(
??? new InputStreamReader(list)); // 创建字符输入流 ??? String data = null;
??? // 读取输入流中的文件目录
??? while ((data = br.readLine()) != null) {
??? // 创建FTP文件对象
??? FtpFile ftpFile = new FtpFile();
??? // 获取FTP服务器目录信息
??? String dateStr = data.substring(39, 51).trim(); ??? String sizeOrDir = data.substring(23, 38).trim(); ??? String fileName = data.substring(52, data.length()) ??? .trim();
??? // 将FTP目录信息初始化到FTP文件对象中
??? ftpFile.setLastDate(dateStr);
??? ftpFile.setSize(sizeOrDir);
??? ftpFile.setName(fileName);
??? ftpFile.setPath(pwd);
??? // 将文件信息添加到表格中
??? model.addRow(new Object[] { ftpFile,
ftpFile.getSize(),
??? dateStr });
??? }
??? br.close(); // 关闭输入流
???
**********************************************************************/ ???
??? } catch (IOException ex) {
??? Logger.getLogger(FTPClientFrame.class.getName()).log( ??? Level.SEVERE, null, ex);
??? }
??? }
??? };
??? if (SwingUtilities.isEventDispatchThread()) // 启动线程对象 ??? runnable.run();
??? else
??? SwingUtilities.invokeLater(runnable);
??? }
???
???
??? /**
??? * 设置FTP连接,并启动下载队列线程的方法
??? */
??? public void setFtpClient(FtpClient ftpClient) {
??? this.ftpClient = ftpClient;
??? // 以30秒为间隔与服务器保持通讯
??? final Timer timer = new Timer(3000, new ActionListener() { ??? @Override
??? public void actionPerformed(ActionEvent e) {
??? try {
??? final FtpClient ftpClient = FtpPanel.this.ftpClient; ??? if (ftpClient != null && ftpClient.serverIsOpen()) { ??? ftpClient.noop();
??? }
??? } catch (IOException e1) {
??? e1.printStackTrace();
??? }
??? }
??? });
??? timer.start();
??? startDownThread();
??? }
???
??? /**
??? * 刷新FTP资源管理面板的当前文件夹
??? */
??? public void refreshCurrentFolder() {
??? try {
??? // 获取服务器文件列表
??? TelnetInputStream list = ftpClient.list(); ??? listFtpFiles(list); // 调用解析方法 ??? } catch (IOException e) {
??? e.printStackTrace();
??? }
??? }
???
??? /**
??? * 开始下载队列线程
??? */
??? private void startDownThread() {
??? if (thread != null)
??? thread.stopThread();
??? thread = new DownThread(this);
??? thread.start();
??? }
???
??? /**
??? * 停止下载队列线程
??? */
??? public void stopDownThread() {
??? if (thread != null) {
??? thread.stopThread();
??? ftpClient = null;
??? }
??? }
???
??? public String getPwd() {
??? String pwd = null;
??? try {
??? pwd = ftpClient.pwd();
??? } catch (IOException e) {
??? e.printStackTrace();
??? }
??? return pwd;
??? }
???
??? public Queue<Object[]> getQueue() {
??? return queue;
??? }
???
??? /**
??? * 清除FTP资源表格内容的方法
??? */
??? public void clearTable() {
??? FtpTableModel model = (FtpTableModel) ftpDiskTable.getModel(); ??? model.setRowCount(0);
??? }
??? }