博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
增强的Java FTP工具----扩展免费版的edtftpj
阅读量:6638 次
发布时间:2019-06-25

本文共 11756 字,大约阅读时间需要 39 分钟。

增强的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 == 
null
return 
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 

 

 
进行测试:
这里只给出测试大概过程:
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,如需转载请自行联系原作者
你可能感兴趣的文章
希尔排序
查看>>
快速排序
查看>>
模板方法模式
查看>>
工厂模式
查看>>
建造者模式
查看>>
unity基础知识
查看>>
享元模式
查看>>
DoTween插件
查看>>
unity坐标系
查看>>
unity坐标系02
查看>>
unity物体移动Transform.Translat
查看>>
实现单滑页效果
查看>>
对象池
查看>>
unity编辑器扩展
查看>>
Json解析
查看>>
C#文件操作
查看>>
责任链模式
查看>>
进程线程
查看>>
生命周期
查看>>
枚举器和迭代器以及unity协程
查看>>