增强的Java FTP工具----扩展免费版的edtftpj

简介:
增强的Java FTP工具----扩展免费版的edtftpj
 
edtftpjs是国外的一个公司所做。有免费版、企业版之分,还有不用语言的版本。商业版的功能强大,是非常优秀的FTP组建。免费的凑合能用,但是功能相对简单,实现粗糙。使用起来问题多多。
 
为了让免费版的edtftpj工具也具有商业版的一些强劲功能,本人利用业余时间做了扩展,经过测试可以正常使用。其中的算法也许不是最好,也欢迎高人提供更好的算法。
 
扩展的主要围绕最常用的功能来进行:
1、增强上传下载功能,使其支持文件和文件夹,如果是文件夹,上传下载保持源的目录结构。
2、增强判断文件、文件夹是否存在的方法,使得ftp的文件操作如本地文件File操作一样容易。
3、添加判断是否为文件、是否为目录的方法。
4、增加FTP配置管理的工具实现,这个不是主要的,就不贴了。
 
环境:
Java SE 1.5
edtftpjs-2.03 free版
 
 
实现思路:
继承FTP客户端核心的类com.enterprisedt.net.ftp.FileTransferClient,添加一些更为通用的有效的方法。本身考虑到覆盖,感觉不妥。就扩展吧!
 
实现代码:
import com.enterprisedt.net.ftp.FTPException; 
import com.enterprisedt.net.ftp.FileTransferClient; 
import com.enterprisedt.net.ftp.WriteMode; 
import org.apache.commons.logging.Log; 
import org.apache.commons.logging.LogFactory; 
import zzvcom.cms.ccm.commons.StringTookit; 

import java.io.File; 
import java.io.IOException; 
import java.text.ParseException; 

/** 
* FTP增强工具 

* @author leizhimin 2008-12-13 16:13:01 
*/
 
public  class UltraFTPClient  extends FileTransferClient { 
         private  static Log log = LogFactory.getLog(UltraFTPClient. class); 

         public UltraFTPClient() { 
        } 

         /** 
         * 下载文件(夹),在本地保持FTP上的目录结构 
         * 
         * @param localFolderPath 本地存放文件夹 
         * @param remotePath            远程文件(夹)路径 
         * @param remoteSubPath     远程文件存放相对根目录 
         * @throws FTPException 
         * @throws IOException 
         */
 
         public  void ftpDownload( final String localFolderPath,  final String remotePath, String remoteSubPath)  throws FTPException, IOException, ParseException { 
                 if (isDir(remoteSubPath)) { 
                        String localPath = localFolderPath + StringTookit.getRelativeRootPath(remoteSubPath, StringTookit.getParentPath(remotePath)); 
                         if (! new File(localPath).exists()) 
                                 new File(localPath).mkdirs(); 
                        String[] x = directoryNameList(remoteSubPath,  false); 
                         for (String fname : x) { 
                                String rmFilePath = StringTookit.formatPath(remoteSubPath +  "/" + fname); 
                                 if (isDir(rmFilePath)) { 
                                        ftpDownload(localFolderPath, remotePath, rmFilePath); 
                                }  else { 
                                        String _localPath = localFolderPath +  "/" + 
                                                        StringTookit.getRelativeRootPath(rmFilePath, StringTookit.getParentPath(remotePath)); 
                                        downloadFile(_localPath, rmFilePath, WriteMode.OVERWRITE); 
                                } 
                        } 
                }  else  if (isFile(remotePath)) { 
                        String localPath = localFolderPath + StringTookit.getRelativeRootPath(remoteSubPath, remotePath); 
                        downloadFile(localPath, remoteSubPath, WriteMode.OVERWRITE); 
                }  else { 
                        log.error( "所下载的文件或文件夹不存在,请检查!"); 
                } 
                log.info( "FTP下载从服务器上的" + remoteSubPath +  "下载到本地" + localFolderPath +  "结束!"); 
        } 

         /** 
         * 上传文件(夹),在FTP上保持本地的目录结构 
         * 
         * @param localFile         本地文件 
         * @param localFilePath 本地文件的路径 
         * @param remoteSubPath 远程文件存放相对根目录 
         * @throws IOException 
         * @throws FTPException 
         */
 
         public  void ftpUpload(File localFile,  final String localFilePath,  final String remoteSubPath)  throws IOException, FTPException { 
                 if (localFile.isDirectory()) { 
                         for (File file : localFile.listFiles()) { 
                                 if (file.isDirectory()) { 
                                        String remotePath = StringTookit.formatPath(remoteSubPath) + StringTookit.getRelativeRootPath(file.getPath(), StringTookit.getParentPath(localFilePath)); 
                                        log.info(remotePath); 
                                         if (!isExist(remotePath)) createDirectory(remotePath); 
                                        ftpUpload(file, localFilePath, remoteSubPath); 
                                }  else { 
                                        String remotePath = StringTookit.formatPath(remoteSubPath) + 
                                                        StringTookit.getRelativeRootPath(file.getPath(), StringTookit.getParentPath(localFilePath)); 
                                        uploadFile(file.getPath(), remotePath, WriteMode.APPEND); 
                                } 
                        } 
                }  else  if (localFile.isFile()) { 
                        String remotePath = StringTookit.formatPath(remoteSubPath) + 
                                        StringTookit.getRelativeRootPath(localFile.getPath(), StringTookit.getParentPath(localFilePath)); 
                         if (!isExist(StringTookit.getParentPath(remotePath))) 
                                createDirectory(StringTookit.getParentPath(remotePath)); 
                        System.out.println(remotePath); 
                        uploadFile(localFile.getPath(), remotePath, WriteMode.APPEND); 
                } 
                log.info( "FTP上传" + localFile.getPath() +  "到" + remoteSubPath +  "目录下结束!"); 
        } 

         /** 
         * @param remotePath 远程文件(夹)路径 
         * @return 远程的文件(夹)资源是否存在 
         */
 
         public  boolean isExist(String remotePath) { 
                 boolean flag =  true
                 try { 
                        directoryList(remotePath); 
                }  catch (Exception e) { 
                        flag =  false
                } 
                 return flag; 
        } 

         /** 
         * @param remotePath 远程文件(夹)路径 
         * @return 当远程资源存在且为文件时返回ture,否则返回false 
         */
 

         public  boolean isFile(String remotePath) { 
                 try { 
                         int size = directoryList(remotePath).length; 
                         if (size >= 0) { 
                                 if (exists(remotePath)) { 
                                         return  true
                                } 
                        } 
                }  catch (Exception e) { 
                } 
                 return  false
        } 

         /** 
         * @param remotePath 远程文件(夹)路径 
         * @return 当远程资源存在且为文件夹时返回ture,否则返回false 
         */
 
         public  boolean isDir(String remotePath) { 
                 try { 
                         int size = directoryList(remotePath).length; 
                         if (size >= 0) { 
                                 if (exists(remotePath)) { 
                                         return  false
                                }  else { 
                                         return  true
                                } 
                        } 
                }  catch (Exception e) { 
                } 
                 return  false
        } 

 
 
为了支持目录运算与不同操作系统的兼容性,写了一个文件路径处理工具。有了这一整套的工具后,上面的工作才能更清晰的去做。
/** 
* 字符串工具箱 

* @author leizhimin 2008-12-15 22:40:12 
*/
 
public  final  class StringTookit { 
         /** 
         * 将一个字符串的首字母改为大写或者小写 
         * 
         * @param srcString 源字符串 
         * @param flag            大小写标识,ture小写,false大些 
         * @return 改写后的新字符串 
         */
 
         public  static String toLowerCaseInitial(String srcString,  boolean flag) { 
                StringBuilder sb =  new StringBuilder(); 
                 if (flag) { 
                        sb.append(Character.toLowerCase(srcString.charAt(0))); 
                }  else { 
                        sb.append(Character.toUpperCase(srcString.charAt(0))); 
                } 
                sb.append(srcString.substring(1)); 
                 return sb.toString(); 
        } 

         /** 
         * 将一个字符串按照句点(.)分隔,返回最后一段 
         * 
         * @param clazzName 源字符串 
         * @return 句点(.)分隔后的最后一段字符串 
         */
 
         public  static String getLastName(String clazzName) { 
                String[] ls = clazzName.split( "\\."); 
                 return ls[ls.length - 1]; 
        } 

         /** 
         * 格式化文件路径,将其中不规范的分隔转换为标准的分隔符,并且去掉末尾的"/"符号。 
         * 
         * @param path 文件路径 
         * @return 格式化后的文件路径 
         */
 
         public  static String formatPath(String path) { 
                String reg =  "\\\\+|/+"
                String temp = path.trim().replaceAll(reg,  "/"); 
                 if (temp.endsWith( "/")) { 
                         return temp.substring(0, temp.length() - 1); 
                } 
                 return temp; 
        } 

         /** 
         * 获取文件父路径 
         * 
         * @param path 文件路径 
         * @return 文件父路径 
         */
 
         public  static String getParentPath(String path) { 
                 return  new File(path).getParent(); 
        } 

         /** 
         * 获取相对路径 
         * 
         * @param fullPath 全路径 
         * @param rootPath 根路径 
         * @return 相对根路径的相对路径 
         */
 
         public  static String getRelativeRootPath(String fullPath, String rootPath) { 
                String relativeRootPath =  null
                String _fullPath = formatPath(fullPath); 
                String _rootPath = formatPath(rootPath); 

                 if (_fullPath.startsWith(_rootPath)) { 
                        relativeRootPath = fullPath.substring(_rootPath.length()); 
                }  else { 
                         throw  new RuntimeException( "要处理的两个字符串没有包含关系,处理失败!"); 
                } 
                 if (relativeRootPath ==  nullreturn  null
                 else 
                         return formatPath(relativeRootPath); 
        } 
}
 
FTP客户端配置工具:
一个好的工具,配置也很讲究,这里也不例外,经过精心处理,FTP服务器配置变得轻松自如:
import com.enterprisedt.net.ftp.FTPConnectMode; 
import org.apache.commons.lang.StringUtils; 
import org.apache.commons.logging.Log; 
import org.apache.commons.logging.LogFactory; 
import zzvcom.cms.ccm.commons.JavaXmlTookit; 
import zzvcom.cms.ccm.commons.SysParamsTookit; 

/** 
* FTP配置 

* @author leizhimin 2008-12-5 22:49:39 
*/
 
public  class FtpServerConfigration { 
         private  static  final Log log = LogFactory.getLog(FtpServerConfigration. class); 
         private String username;                 //用户名 
         private String password;                 //密码 
         private String ip;                             //ip 
         private Integer port;                      //端口 
         private Integer timeout;                 //超时时间 
         private Integer buffersize;          //缓存大小 
         private Integer notifytime;          //通知时间 
         private String connectMode;          //连接模式 
         private String encoding;                 //编码方式 

         public FtpServerConfigration(String username, String password, String ip, Integer port) { 
                 this.username = username; 
                 this.password = password; 
                 this.ip = ip; 
                 this.port = port; 
                 this.timeout = Integer.valueOf(SysParamsTookit.getProperty( "timeout""36000000")); 
                 this.buffersize = Integer.valueOf(SysParamsTookit.getProperty( "buffersize""2048000")); 
                 this.notifytime = Integer.valueOf(SysParamsTookit.getProperty( "notifytime""5000")); 
                 this.connectMode = SysParamsTookit.getProperty( "connectMode""PASV"); 
                 this.encoding = SysParamsTookit.getProperty( "encoding""GBK"); 
        } 

         public FtpServerConfigration(String ftpConfigXml) { 
                FtpServerConfigration config = (FtpServerConfigration) JavaXmlTookit.xml2Java(ftpConfigXml, FtpServerConfigration. class); 
                 if (StringUtils.isBlank(config.getUsername()) 
                                || StringUtils.isBlank(config.getPassword()) 
                                || StringUtils.isBlank(config.getIp()) 
                                || config.getPort() ==  null) { 
                        log.error( "FTP最基本的配置属性(username、password、ip、port)不能为空,请检查!"); 
                }  else { 
                         this.username = config.getUsername(); 
                         this.password = config.getPassword(); 
                         this.ip = config.getIp(); 
                         this.port = config.getPort(); 
                } 
                 if (config.getTimeout() ==  null
                         this.timeout = Integer.valueOf(SysParamsTookit.getProperty( "timeout""36000000")); 
                 if (config.getBuffersize() ==  null
                         this.buffersize = Integer.valueOf(SysParamsTookit.getProperty( "buffersize""2048000")); 
                 if (config.getNotifytime() ==  null
                         this.notifytime = Integer.valueOf(SysParamsTookit.getProperty( "notifytime""5000")); 
                 if (StringUtils.isBlank(config.getConnectMode())) 
                         this.connectMode = SysParamsTookit.getProperty( "connectMode""PASV"); 
                 if (StringUtils.isBlank(config.getEncoding())) 
                         this.encoding = SysParamsTookit.getProperty( "encoding""GBK"); 
        } 

         /** 
         * 获取当前FTP连接配置 
         * 
         * @return 当前FTP连接配置 
         */
 
         public FtpServerConfigration getConfigration() { 
                 return  this
        } 

         /** 
         * 构建FTP客户端连接,并进行连接 
         * 
         * @return FTP客户端连接 
         * @throws Exception 当构建客户端失败时抛出 
         */
 
         public UltraFTPClient buildFtpClient()  throws Exception { 
                UltraFTPClient client =  new UltraFTPClient(); 
                 try { 
                        client.setUserName(username); 
                        client.setPassword(password); 
                        client.setRemoteHost(ip); 
                        client.setRemotePort(port); 
                        client.setTimeout(timeout); 
                        client.getAdvancedSettings().setTransferBufferSize(buffersize); 
                        client.getAdvancedSettings().setTransferNotifyInterval(notifytime); 
                        client.getAdvancedSettings().setControlEncoding(encoding); 
                       // client.setEventListener( new UploadListener(client));                 //设置事件监听器 
                         if (connectMode.equalsIgnoreCase( "ACTIVE")) { 
                                client.getAdvancedFTPSettings().setConnectMode(FTPConnectMode.ACTIVE);  //设置为被动模式 
                        }  else  if (connectMode.equalsIgnoreCase( "PASV")) { 
                                client.getAdvancedFTPSettings().setConnectMode(FTPConnectMode.PASV);  //设置为被动模式 
                        }  else { 
                                log.error( "标识为" + connectMode +  "的FTP连接模式配置错误,连接模式仅有两种ACTIVE和PASV,请检查!"); 
                        } 
                        client.connect(); 
                        log.info( "FTP连接成功!详细信息(远程主机:" + ip +  ",用户名:" + username +  ")"); 
                }  catch (Exception e) { 
                        log.info( "FTP创建连接发生异常!", e); 
                         throw e; 
                } 
                 return client; 
        } 

         public String getUsername() { 
                 return username; 
        } 

         public  void setUsername(String username) { 
                 this.username = username; 
        } 

         public String getPassword() { 
                 return password; 
        } 

         public  void setPassword(String password) { 
                 this.password = password; 
        } 

         public String getIp() { 
                 return ip; 
        } 

         public  void setIp(String ip) { 
                 this.ip = ip; 
        } 

         public Integer getPort() { 
                 return port; 
        } 

         public  void setPort(Integer port) { 
                 this.port = port; 
        } 

         public Integer getTimeout() { 
                 return timeout; 
        } 

         public  void setTimeout(Integer timeout) { 
                 this.timeout = timeout; 
        } 

         public Integer getBuffersize() { 
                 return buffersize; 
        } 

         public  void setBuffersize(Integer buffersize) { 
                 this.buffersize = buffersize; 
        } 

         public Integer getNotifytime() { 
                 return notifytime; 
        } 

         public  void setNotifytime(Integer notifytime) { 
                 this.notifytime = notifytime; 
        } 

         public String getConnectMode() { 
                 return connectMode; 
        } 

         public  void setConnectMode(String connectMode) { 
                 this.connectMode = connectMode; 
        } 

         public String getEncoding() { 
                 return encoding; 
        } 

         public  void setEncoding(String encoding) { 
                 this.encoding = encoding; 
        } 
}
 
系统默认的FtP参数配置:
### FTP默认配置参数 ### 
# FTP连接模式:ACTIVE,PASV为两种连接模式 
#port=21 
ftp.timeout=360000 
ftp.buffersize=20480 
ftp.notifytime=5000 
ftp.connectMode=PASV 
ftp.encoding=GBK 
 
进行测试:
这里只给出测试大概过程:
1、创建一个FTP配置对象,并从FTP配置对象构建一个增强的FTP客户端对象。
UltraFTPClient client = new FtpServerConfigration("testuser", "123456", "192.168.0.2", 21).buildFtpClient();
 
2、根据有了客户端后,就可以调用增强的和原有的任何方法,来完成你想要的FTP操作。
 
3、操作完成后关闭FTP连接。
client.disconnect();
 
遗留问题:
FTP的写模式在下载的时候无法指定,指定为WriteMode.APPEND(追加)是最理想的,但是现在无法做到,只要设置就出错。也许是因为我服务器配置的问题,原因不明。
如果您解决了遗留问题,或者发现了新的问题,也请留言告诉我。
 
题外话:
下一步本人将利用业余时间使用Apache的Commons Net提供的基础API来实现这个FTP客户端。
一个人的精力和能力都是有限的,希望这个FTP客户端将来能成为一个颇受欢迎的开源组件,任何人都可以轻松使用其构建自己的FTP应用。


本文转自 leizhimin 51CTO博客,原文链接:http://blog.51cto.com/lavasoft/120337,如需转载请自行联系原作者
相关文章
|
1月前
|
Java
java小工具util系列5:java文件相关操作工具,包括读取服务器路径下文件,删除文件及子文件,删除文件夹等方法
java小工具util系列5:java文件相关操作工具,包括读取服务器路径下文件,删除文件及子文件,删除文件夹等方法
68 9
|
2月前
|
监控 Java 测试技术
Java开发现在比较缺少什么工具?
【10月更文挑战第15天】Java开发现在比较缺少什么工具?
37 1
|
22天前
|
SQL Java 索引
java小工具util系列2:字符串工具
java小工具util系列2:字符串工具
137 83
|
19天前
|
Java 开发者 微服务
Spring Boot 入门:简化 Java Web 开发的强大工具
Spring Boot 是一个开源的 Java 基础框架,用于创建独立、生产级别的基于Spring框架的应用程序。它旨在简化Spring应用的初始搭建以及开发过程。
38 6
Spring Boot 入门:简化 Java Web 开发的强大工具
|
22天前
|
Java 数据库
java小工具util系列1:日期和字符串转换工具
java小工具util系列1:日期和字符串转换工具
53 26
|
23天前
|
Java
java小工具util系列4:基础工具代码(Msg、PageResult、Response、常量、枚举)
java小工具util系列4:基础工具代码(Msg、PageResult、Response、常量、枚举)
48 24
|
22天前
|
数据采集 存储 监控
Java爬虫:数据采集的强大工具
在数据驱动的时代,Java爬虫技术凭借其强大的功能和灵活性,成为企业获取市场信息、用户行为及竞争情报的关键工具。本文详细介绍了Java爬虫的工作原理、应用场景、构建方法及其重要性,强调了在合法合规的前提下,如何有效利用Java爬虫技术为企业决策提供支持。
|
1月前
|
Java 数据格式 索引
使用 Java 字节码工具检查类文件完整性的原理是什么
Java字节码工具通过解析和分析类文件的字节码,检查其结构和内容是否符合Java虚拟机规范,确保类文件的完整性和合法性,防止恶意代码或损坏的类文件影响程序运行。
44 5
|
1月前
|
Java API Maven
如何使用 Java 字节码工具检查类文件的完整性
本文介绍如何利用Java字节码工具来检测类文件的完整性和有效性,确保类文件未被篡改或损坏,适用于开发和维护阶段的代码质量控制。
76 5
|
2月前
|
Web App开发 Java
使用java操作浏览器的工具selenium-java和webdriver下载地址
【10月更文挑战第12天】Selenium-java依赖包用于自动化Web测试,版本为3.141.59。ChromeDriver和EdgeDriver分别用于控制Chrome和Edge浏览器,需确保版本与浏览器匹配。示例代码展示了如何使用Selenium-java模拟登录CSDN,包括设置驱动路径、添加Cookies和获取页面源码。
131 6
下一篇
DataWorks