生成ftp文件的目录树

时间:2021-08-29 12:33:26

依赖

<dependency>
            <groupId>commons-net</groupId>
            <artifactId>commons-net</artifactId>
            <version>3.4</version>
        </dependency>

        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.3.2</version>
        </dependency>

节点对象

package per.qiao.utils.ftp;

/**
 * Create by IntelliJ Idea 2018.2
 *
 * @author: qyp
 * Date: 2019-07-19 22:14
 */

import lombok.Data;

import java.util.List;

@Data
public class Node {

    private enum TYPE {
        DIR("DIR"),
        FILE("FILE")
        ;
        private String type;
        private TYPE(String type) {
            this.type = type;
        }
        public String getType() {
            return this.type;
        }
    }

    private String id;
    private String name;
    private String path;
    private TYPE type;

    private List<Node> childList;
    private Node() {}

    private Node(String id, String name, String path, TYPE type) {
        this.id = id;
        this.name = name;
        this.path = path;
        this.type = type;
    }

    public static Node getDirNode(String id, String name, String path) {
        return new Node(id, name, path, TYPE.DIR);
    }
    public static Node getFileNode(String id, String name, String path) {
        return new Node(id, name, path, TYPE.FILE);
    }
}

生成节点目录树结构

package per.qiao.utils.ftp;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * Create by IntelliJ Idea 2018.2
 *
 * @author: qyp
 * Date: 2019-07-19 21:27
 */

public class FtpUtils {

    private final static Logger logger = LoggerFactory.getLogger(FtpUtils.class);

    /**
     * 本地连接
     * @return
     */
    public static FTPClient localConn() {
        String server = "127.0.0.1";
        int port = 21;
        String username = "test";
        String password = "test";
//        path = "/FTPStation/";

        FTPClient ftpClient = null;
        try {
            ftpClient = connectServer(server, port, username, password, "/");
        } catch (IOException e) {
            e.printStackTrace();
        }
        return ftpClient;
    }

    /**
     *
     * @param server
     * @param port
     * @param username
     * @param password
     * @param path 连接的节点(相对根路径的文件夹)
     * @return
     */
    public static FTPClient connectServer(String server, int port, String username, String password, String path) throws IOException {
        path = path == null ? "" : path;
        FTPClient ftp = new FTPClient();

        //下面四行代码必须要,而且不能改变编码格式,否则不能正确下载中文文件
        // 如果使用serv-u发布ftp站点,则需要勾掉“高级选项”中的“对所有已收发的路径和文件名使用UTF-8编码”
        ftp.setControlEncoding("GBK");
        FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_NT);
        conf.setServerLanguageCode("zh");
        ftp.configure(conf);

        // 判断ftp是否存在
        ftp.connect(server, port);
        ftp.setDataTimeout(2 * 60 * 1000);
        if (!FTPReply.isPositiveCompletion(ftp.getReplyCode())) {
            ftp.disconnect();
            System.out.println(server + "拒绝连接");
        }
        //登陆ftp
        boolean login = ftp.login(username, password);
        if (logger.isDebugEnabled()) {
            if (login) {
                logger.debug("登陆FTP成功! ip: " + server);
            } else {
                logger.debug("登陆FTP失败! ip: " + server);
            }
        }

        //根据输入的路径,切换工作目录。这样ftp端的路径就可以使用相对路径了
        exchageDir(path, ftp);

        return ftp;
    }
    
    /**
     * 切换目录 返回切换的层级数
     * @param path
     * @param ftp
     * @return 切换的层级数
     * @throws IOException
     */
    private static int exchageDir(String path, FTPClient ftp) {
        // 切换的次数(层级),方便回退
        int level = 0;

        try {
            if (StringUtils.isNotBlank(path)) {
                // 对路径按照 '/' 进行切割,一层一层的进入
                String[] pathes = path.split("/");
                for (String onepath : pathes) {
                    if (onepath == null || "".equals(onepath.trim())) {
                        continue;
                    }
                    //文件排除
                    if (onepath.contains(".")) {
                        continue;
                    }
                    boolean flagDir = ftp.changeWorkingDirectory(onepath);
                    if (flagDir) {
                        level ++;
                        logger.info("成功连接ftp目录:" + ftp.printWorkingDirectory());
                    } else {
                        logger.warn("连接ftp目录失败:" + ftp.printWorkingDirectory());
                    }
                }
            }
        } catch (IOException e) {
            logger.error("切换失败, 路径不存在");
            e.printStackTrace();
            throw new IllegalArgumentException("切换失败, 路径不存在");
        }
        return level;
    }

    /**
     * 生成目录树
     * @return
     */
    public static Node getTree(String path) {
        FTPClient ftp = localConn();
        exchageDir(path, ftp);
        String rootNodeName = path.substring(path.lastIndexOf("/") + 1);
        Node rootNode = Node.getDirNode(getId(), rootNodeName, path);
        listTree(ftp, path, rootNode);
        return rootNode;
    }

    /**
     * 遍历树结构
     * @param ftp
     * @param rootPath
     * @param parentNode
     */
    private static void listTree(FTPClient ftp, String rootPath, Node parentNode) {

        try {
            FTPFile[] ftpFiles = ftp.listFiles();
            if (ftpFiles.length <= 0) {
                return;
            }
            for (FTPFile f : ftpFiles) {
                List<Node> childList = parentNode.getChildList();
                if (childList == null) {
                    childList = new ArrayList<>();
                    parentNode.setChildList(childList);
                }
                Node currentNode = null;
                if (f.isDirectory()) {
                    currentNode = Node.getDirNode(getId(), f.getName(), rootPath + File.separator + f.getName());
                    if (ftp.changeWorkingDirectory(f.getName()) ) {
                        if (logger.isDebugEnabled()) {
                            logger.debug("进入:", ftp.printWorkingDirectory());
                        }
                        listTree(ftp, rootPath + File.separator + f.getName(), currentNode);
                    }
                    ftp.changeToParentDirectory();
                    if (logger.isDebugEnabled()) {
                        logger.debug("退出: {}", ftp.printWorkingDirectory());
                    }
                } else {
                    currentNode = Node.getFileNode(getId(), f.getName(), rootPath + File.separator + f.getName());
                }
                childList.add(currentNode);
            }
        } catch (IOException e) {
            e.printStackTrace();
            logger.error("路径不存在");
        }

    }

    private static String getId() {
        return UUID.randomUUID().toString().replaceAll("-", "");
    }

    public static void main(String[] args) {
        Node rootNode = getTree("/CAD/第一层");
        System.out.println(rootNode);
    }

}