• 增强的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
    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(追加)是最理想的,但是现在无法做到,只要设置就出错。也许是因为我服务器配置的问题,原因不明。
  • 相关阅读:
    高性能解决线程饥饿的利器 StampedLock
    月初刚拿到美团offer,新鲜的美团现场面试41题(三面技术+HR面)
    这两份Java“并发+异步”编程宝典,堪称编程界的“瑰宝”
    阿里架构师的学习笔记:多线程+JVM+Mysql+Redis+设计模式
    打造多模块+高可用+高扩展Spring Cloud版分布式电商项目源码分享
    想要彻底搞懂微服务架构必先学:SpringBoot+SpringCloud+docker
    厉害了!阿里P8手写《springboot 核心》PDF来了
    阿里P8熬夜总结Spring源码笔记,上线3分钟“全网跪求”
    UFLDL课程学习(二)
    UFLDL课程学习(一)
  • 原文地址:https://www.cnblogs.com/cuker919/p/4878614.html
Copyright © 2020-2023  润新知