热门标签 | HotTags
当前位置:  开发笔记 > 运维 > 正文

Java语言实现简单FTP软件FTP上传下载管理模块实现(11)

这篇文章主要为大家详细介绍了Java语言实现简单FTP软件,FTP本地文件管理模块的实现方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

本文为大家分享了FTP上传下载管理模块的实现方法,供大家参考,具体内容如下

1、上传本地文件或文件夹到远程FTP服务器端的功能。

当用户在本地文件列表中选择想要上传的文件后,点击上传按钮,将本机上指定的文件上传到FTP服务器当前展现的目录,下图为上传子模块流程图

选择好要上传的文件或文件夹,点击“上传”按钮,会触发com.oyp.ftp.panel.local.UploadAction类的actionPerformed(ActionEvent e)方法,其主要代码如下

/** 
 * 上传文件动作的事件处理方法 
 */ 
public void actionPerformed(java.awt.event.ActionEvent evt) { 
 // 获取用户选择的多个文件或文件夹 
 int[] selRows = this.localPanel.localDiskTable.getSelectedRows(); 
 if (selRows.length <1) { 
  JOptionPane.showMessageDialog(this.localPanel, "请选择上传的文件或文件夹"); 
  return; 
 } 
 // 获取FTP服务器的当前路径 
 String pwd = this.localPanel.frame.getFtpPanel().getPwd(); 
 // 创建FTP当前路径的文件夹对象 
 FtpFile ftpFile = new FtpFile("", pwd, true); 
 // 遍历本地资源的表格 
 for (int i = 0; i 

在com.oyp.ftp.panel.local.UploadThread线程类的run()方法,会判断上传队列是否有对象,如果有则调用其copyFile(File file, FtpFile ftpFile)方法实现上传文件的功能,上传完后刷新远程FTP文件管理的面板。其run()方法主要代码如下

 * 线程的主体方法 
 */ 
public void run() { // 线程的主体方法 
 while (conRun) { 
  try { 
   Thread.sleep(1000); // 线程休眠1秒 
   Queue queue = localPanel.queue; // 获取本地面板的队列对象 
   queueValues = queue.peek(); // 获取队列首的对象 
   if (queueValues == null) { // 如果该对象为空 
    continue; // 进行下一次循环 
   } 
   File file = (File) queueValues[0]; // 获取队列中的本队文件对象 
   FtpFile ftpFile = (FtpFile) queueValues[1]; // 获取队列中的FTP文件对象 
   if (file != null) { 
    selPath = file.getParent(); 
    copyFile(file, ftpFile); // 调用递归方法上传文件 
    FtpPanel ftpPanel = localPanel.frame.getFtpPanel(); 
    ftpPanel.refreshCurrentFolder(); // 刷新FTP面板中的资源 
   } 
   Object[] args = queue.peek(); 
   // 判断队列顶是否为处理的上一个任务。 
   if (queueValues == null || args == null 
     || !queueValues[0].equals(args[0])) { 
    continue; 
   } 
   queue.remove(); // 移除队列首元素 
  } catch (Exception e) { 
   e.printStackTrace(); 
  } 
 } 
} 

其中调用的copyFile(File file, FtpFile ftpFile)方法代码如下

  /** 
  * 上传线程的递归方法,上传文件夹的所有子文件夹和内容 
  * @param file 
  *   - FTP文件对象 
  * @param localFolder 
  *   - 本地文件夹对象 
  */ 
 private void copyFile(File file, FtpFile ftpFile) { // 递归遍历文件夹的方法 
  // 判断队列面板是否执行暂停命令 
  while (localPanel.frame.getQueuePanel().isStop()) { 
   try { 
    Thread.sleep(1000); 
   } catch (InterruptedException e) { 
    e.printStackTrace(); 
   } 
  } 
 
  Object[] args = localPanel.queue.peek(); 
  // 判断队列顶是不是上一个处理的任务。 
  if (queueValues == null || args == null 
    || !queueValues[0].equals(args[0])) 
   return; 
  try { 
//   System.out.println("selPath:"+selPath); 
   path = file.getParentFile().getPath().replace(selPath, ""); 
//   System.out.println("path:"+path); 
   ftpFile.setName(path.replace("\\", "/")); 
   path = ftpFile.getAbsolutePath(); 
//   System.out.println("ftpFile.getAbsolutePath():"+path); 
   if (file.isFile()) { 
    UploadPanel uploadPanel = localPanel.frame.getUploadPanel();//上传面板 
    String remoteFile = path + "/" + file.getName(); // 远程FTP的文件名绝对路径 
//    System.out.println("remoteFile:" + remoteFile); 
    double fileLength = file.length() / Math.pow(1024, 2); 
    ProgressArg progressArg = new ProgressArg( 
      (int) (file.length() / 1024), 0, 0);//进度参数 
    String size = String.format("%.4f MB", fileLength); 
    Object[] row = new Object[] { file.getAbsoluteFile(), size, 
      remoteFile, ftpClient.getServer(), progressArg }; 
    uploadPanel.addRow(row); //添加列 
    OutputStream put = ftpClient.put(remoteFile); // 获取服务器文件的输出流 
    FileInputStream fis = null; // 本地文件的输入流 
    try { 
     fis = new FileInputStream(file); // 初始化文件的输入流 
    } catch (Exception e) { 
     e.printStackTrace(); 
     return; 
    } 
    int readNum = 0; 
    byte[] data = new byte[1024]; // 缓存大小 
    while ((readNum = fis.read(data)) > 0) { // 读取本地文件到缓存 
     Thread.sleep(0, 30); // 线程休眠 
     put.write(data, 0, readNum); // 输出到服务器 
     progressArg.setValue(progressArg.getValue() + 1);// 累加进度条 
    } 
    progressArg.setValue(progressArg.getMax()); // 结束进度条 
    fis.close(); // 关闭文件输入流 
    put.close(); // 关闭服务器输出流 
   } else if (file.isDirectory()) { 
    path = file.getPath().replace(selPath, ""); 
    ftpFile.setName(path.replace("\\", "/")); 
//    System.out.println("Dirpath:"+path); 
    /**将目录切换到当前FTP服务器的当前目录*/ 
    ftpClient.cd(this.localPanel.frame.getFtpPanel().getPwd());  // /media目录 
    /** 
     * 如果有创建文件夹的权限,则在当前FTP服务器的当前目录下创建文件夹 
     * 必须要有创建文件夹的权限,否则会报错 
     *  path:audio 
      ftpFile.getAbsolutePath():/media/audio 
      remoteFile:/media/audio/梁静茹-会呼吸的痛Live.mp3 
     */ 
    ftpClient.sendServer("MKD " + path + "\r\n"); //创建 /media/audio 目录 
    ftpClient.readServerResponse(); 
     
    /*********************************************************** 
     * 如果没有有创建文件夹的权限,则创建文件夹,因此FTP服务器的当前路径下不存在 
     * 那么将文件上传到此FTP服务器的当前路径下 
     * 
     *  如要上传C://audio目录(目录中有 梁静茹-会呼吸的痛Live.mp3 和 林宥嘉-心酸.mp3 两个文件) 
     *  到 FTP服务器上的 /media/ 目录下 
     *  因为FTP服务器上没有 /media/audio 目录,并且FTP服务器当前的目录为 /media 
     *  所以将 C://audio目录下的文件上传到了 /media目录下 
     *  ftpFile.getAbsolutePath():/media/audio 
      remoteFile:/media/梁静茹-会呼吸的痛Live.mp3 
      remoteFile:/media/林宥嘉-心酸.mp3 
     */ 
    //创建一个文件夹对象,检查该文件是否存在 
    File fileRemote=new File(this.localPanel.frame.getFtpPanel().getPwd()+path); //path:audio 
    //该目录不存在 
    if (!fileRemote.exists()) { 
     path=this.localPanel.frame.getFtpPanel().getPwd(); 
    } 
    /***********************************************************/ 
     
    File[] listFiles = file.listFiles(); 
    for (File subFile : listFiles) { 
     Thread.sleep(0, 50); 
     copyFile(subFile, ftpFile); 
    } 
   } 
  } catch (FileNotFoundException e1) { 
   e1.printStackTrace(); 
   System.exit(0); 
   // JOptionPane.showMessageDialog(localPanel, e1.getMessage()); 
  } catch (Exception ex) { 
   ex.printStackTrace(); 
  } 
 } 

2、下载远程FTP服务器端的文件或文件夹到本地

当用户在远程FTP服务器文件列表中选择想要下载的文件后,点击下载按钮,将服务器上的文件下载至本机,下图为下载子模块流程图。

选择好要下载的文件或文件夹,点击“下载”按钮,会触发com.oyp.ftp.panel.ftp.DownAction类的actionPerformed(ActionEvent e)方法,其主要代码如下

  /** 
  * 下载按钮的动作处理器动作的事件处理方法 
 */ 
@Override 
public void actionPerformed(ActionEvent e) { 
 // 获取FTP资源表格的所有选择行 
 final int[] selRows = ftpPanel.ftpDiskTable.getSelectedRows(); 
 if (selRows.length <1) 
  return; 
 // 遍历表格的所有选择行 
 for (int i = 0; i 

在com.oyp.ftp.panel.ftp.DownThread线程类的run()方法,会判断下载队列是否有对象,如果有则调用其downFile(FtpFile file, File localFolder)方法实现上传文件的功能,上传完后刷新远程FTP文件管理的面板。其run()方法代码如下

public void run() { // 线程业务方法 
  while (conRun) { 
   try { 
    Thread.sleep(1000); 
    ftpClient.noop(); 
    queueValues = ftpPanel.queue.peek(); 
    if (queueValues == null) { 
     continue; 
    } 
    FtpFile file = (FtpFile) queueValues[0]; 
    File localFolder = (File) queueValues[1]; 
    if (file != null) { 
     path = file.getPath(); 
     ftpClient.cd(path); 
     downFile(file, localFolder); 
     path = null; 
     ftpPanel.frame.getLocalPanel().refreshCurrentFolder(); 
    } 
    Object[] args = ftpPanel.queue.peek(); 
    // 判断队列顶是否为处理的上一个任务。 
    if (queueValues == null || args == null 
      || !queueValues[0].equals(args[0])) 
     continue; 
    ftpPanel.queue.poll(); 
   } catch (Exception e) { 
    e.printStackTrace(); 
   } 
  } 
 } 

其中调用的downFile(FtpFile file, File localFolder)方法代码如下

/** 
  * 下载线程的递归方法,用户探索FTP下载文件夹的所有子文件夹和内容 
  * @param file FTP文件对象 
  * @param localFolder 本地文件夹对象 
  */ 
 private void downFile(FtpFile file, File localFolder) { 
  // 判断队列面板是否执行暂停命令 
  while (ftpPanel.frame.getQueuePanel().isStop()) { 
   try { 
    Thread.sleep(1000); 
   } catch (InterruptedException e) { 
    e.printStackTrace(); 
   } 
  } 
  Object[] args = ftpPanel.queue.peek(); 
  // 判断队列顶是否为处理的上一个任务。 
  if (queueValues == null || args == null 
    || !queueValues[0].equals(args[0])) 
   return; 
  try { 
   String ftpFileStr = file.getAbsolutePath().replaceFirst(path + "/", 
     ""); 
   if (file.isFile()) { 
    // 获取服务器指定文件的输入流 
    TelnetInputStream ftpIs = ftpClient.get(file.getName()); 
    if (ftpIs == null) { 
     JOptionPane.showMessageDialog(this.ftpPanel, file.getName() 
       + "无法下载"); 
     return; 
    } 
    // 创建本地文件对象 
    File downFile = new File(localFolder, ftpFileStr); 
    // 创建本地文件的输出流 
    FileOutputStream fout = new FileOutputStream(downFile, true); 
    // 计算文件大小 
    double fileLength = file.getLongSize() / Math.pow(1024, 2); 
    ProgressArg progressArg = new ProgressArg((int) (file 
      .getLongSize() / 1024), 0, 0); //进度参数 
    String size = String.format("%.4f MB", fileLength); 
    //"文件名", "大小", "本地文件名","主机", "状态" 
    Object[] row = new Object[] { ftpFileStr, size, 
      downFile.getAbsolutePath(), ftpClient.getServer(), 
      progressArg }; 
    DownloadPanel downloadPanel = ftpPanel.frame.getDownloadPanel(); //下载队列面板 
    downloadPanel.addRow(row); //添加列 
    byte[] data = new byte[1024]; // 定义缓存 
    int read = -1; 
    while ((read = ftpIs.read(data)) > 0) { // 读取FTP文件内容到缓存 
     Thread.sleep(0, 30); // 线程休眠 
     fout.write(data, 0, read); // 将缓存数据写入本地文件 
     // 累加进度条 
     progressArg.setValue(progressArg.getValue() + 1); 
    } 
    progressArg.setValue(progressArg.getMax());// 结束进度条 
    fout.close(); // 关闭文件输出流 
    ftpIs.close(); // 关闭FTP文件输入流 
   } else if (file.isDirectory()) { // 如果下载的是文件夹 
    // 创建本地文件夹对象 
    File directory = new File(localFolder, ftpFileStr); 
    directory.mkdirs(); // 创建本地的文件夹 
    ftpClient.cd(file.getName()); // 改变FTP服务器的当前路径 
    // 获取FTP服务器的文件列表信息 
    TelnetInputStream telnetInputStream=ftpClient.list(); 
    byte[]names=new byte[2048]; 
    int bufsize=0; 
    bufsize=telnetInputStream.read(names, 0, names.length); 
    int i=0,j=0; 
    while(i

功能效果图可以查看以下两篇文章。

Java语言实现简单FTP软件------>FTP软件效果图预览之上传功能(三)

Java语言实现简单FTP软件------>FTP软件效果图预览之下载功能(二)

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


推荐阅读
  • Windows服务与数据库交互问题解析
    本文探讨了在Windows 10(64位)环境下开发的Windows服务,旨在定期向本地MS SQL Server (v.11)插入记录。尽管服务已成功安装并运行,但记录并未正确插入。我们将详细分析可能的原因及解决方案。 ... [详细]
  • 探讨如何通过编程技术实现100个并发连接,解决线程创建顺序问题,并提供高效的并发测试方案。 ... [详细]
  • 梦幻西游挖图奇遇:70级项链意外触发晶清诀,3000W轻松到手
    在梦幻西游中,挖图是一项备受欢迎的活动,无论是小宝图还是高级藏宝图,都吸引了大量玩家参与。通常情况下,小宝图的数量保证了稳定的收益,但特技装备的出现往往能带来意想不到的惊喜。本文讲述了一位玩家通过挖图获得70级晶清项链的故事,最终实现了3000W的游戏币逆袭。 ... [详细]
  • 本文探讨了 RESTful API 和传统接口之间的关键差异,解释了为什么 RESTful API 在设计和实现上具有独特的优势。 ... [详细]
  • 本文详细介绍了Java编程语言中的核心概念和常见面试问题,包括集合类、数据结构、线程处理、Java虚拟机(JVM)、HTTP协议以及Git操作等方面的内容。通过深入分析每个主题,帮助读者更好地理解Java的关键特性和最佳实践。 ... [详细]
  • 如何配置Unturned服务器及其消息设置
    本文详细介绍了Unturned服务器的配置方法和消息设置技巧,帮助用户了解并优化服务器管理。同时,提供了关于云服务资源操作记录、远程登录设置以及文件传输的相关补充信息。 ... [详细]
  • 网络攻防实战:从HTTP到HTTPS的演变
    本文通过一系列日记记录了从发现漏洞到逐步加强安全措施的过程,探讨了如何应对网络攻击并最终实现全面的安全防护。 ... [详细]
  • MQTT技术周报:硬件连接与协议解析
    本周开发笔记重点介绍了在新项目中使用MQTT协议进行硬件连接的技术细节,涵盖其特性、原理及实现步骤。 ... [详细]
  • UNP 第9章:主机名与地址转换
    本章探讨了用于在主机名和数值地址之间进行转换的函数,如gethostbyname和gethostbyaddr。此外,还介绍了getservbyname和getservbyport函数,用于在服务器名和端口号之间进行转换。 ... [详细]
  • 邮件(带附件,模拟文件上传,跨服务器)发送核心代码1.测试邮件发送附件接口***测试邮件发送附件*@parammultipartFile*@return*@RequestMappi ... [详细]
  • 360SRC安全应急响应:从漏洞提交到修复的全过程
    本文详细介绍了360SRC平台处理一起关键安全事件的过程,涵盖从漏洞提交、验证、排查到最终修复的各个环节。通过这一案例,展示了360在安全应急响应方面的专业能力和严谨态度。 ... [详细]
  • 本文深入探讨了Linux系统中网卡绑定(bonding)的七种工作模式。网卡绑定技术通过将多个物理网卡组合成一个逻辑网卡,实现网络冗余、带宽聚合和负载均衡,在生产环境中广泛应用。文章详细介绍了每种模式的特点、适用场景及配置方法。 ... [详细]
  • 本文探讨了在不使用服务器控件的情况下,如何通过多种方法获取并修改页面中的HTML元素值。除了常见的AJAX方式,还介绍了其他可行的技术方案。 ... [详细]
  • 解读MySQL查询执行计划的详细指南
    本文旨在帮助开发者和数据库管理员深入了解如何解读MySQL查询执行计划。通过详细的解析,您将掌握优化查询性能的关键技巧,了解各种访问类型和额外信息的含义。 ... [详细]
  • 掌握远程执行Linux脚本和命令的技巧
    本文将详细介绍如何利用Python的Paramiko库实现远程执行Linux脚本和命令,帮助读者快速掌握这一实用技能。通过具体的示例和详尽的解释,让初学者也能轻松上手。 ... [详细]
author-avatar
uikankan
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有