开发一个spring boot的FTP Starter

Maven依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <!-- 自定义starter都应该继承自该依赖 -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starters</artifactId>
        <version>2.1.6.RELEASE</version>
    </parent>


    <groupId>com.cch</groupId>
    <artifactId>ftp-starter</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>ftp-starter</name>
    <description>ftp client project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <!-- https://mvnrepository.com/artifact/commons-net/commons-net -->
        <dependency>
            <groupId>commons-net</groupId>
            <artifactId>commons-net</artifactId>
            <version>3.6</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.slf4j/log4j-over-slf4j -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>log4j-over-slf4j</artifactId>
            <version>1.7.25</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.25</version>
        </dependency>


    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

配置类

package com.cch.ftpstarter.config;



/*
 * @ClassName:FtpAutoConfiguration
 * @Description TODO
 * @Time 2019-07-08 12:16
 */

import com.cch.ftpstarter.properties.FTPProperties;
import com.cch.ftpstarter.util.FtpClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;

@Configuration
@EnableConfigurationProperties(FTPProperties.class)
@ConditionalOnClass(FtpClient.class)
public class FtpAutoConfiguration {

    @Autowired
    private FTPProperties properties;

    @Bean
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    @ConditionalOnMissingBean(FtpClient.class)// 当容器中没有指定Bean的情况下,自动配置FtpClient类
    public FtpClient ftpClient(){
        FtpClient ftpClient = new FtpClient(properties);
        return ftpClient;
    }

}

在resources下创建META-INF目录

在META-INF目录下创建spring.factories文件

在spring.factories文件中输入

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.cch.ftpstarter.config.FtpAutoConfiguration

属性类

package com.cch.ftpstarter.properties;

/*
 * @ClassName:FTPConfig
 * @Description TODO
 * @Time 2019-07-05 14:14
 */

import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "ftp") // 自动获取配置文件中前缀为ftp的属性,把值传入对象参数
public class FTPProperties {

    private String server = "localhost";
    private Integer port = 21;
    private String user = "";
    private String password = "";

    public String getServer() {
        return server;
    }

    public void setServer(String server) {
        this.server = server;
    }

    public Integer getPort() {
        return port;
    }

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

    public String getUser() {
        return user;
    }

    public void setUser(String user) {
        this.user = user;
    }

    public String getPassword() {
        return password;
    }

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


FTP操作类(spring bean) 

package com.cch.ftpstarter.util;



/*
 * @ClassName:FtpClient
 * @Description ftp客户端操作类
 * @Time 2019-07-04 18:46
 */

import com.cch.ftpstarter.properties.FTPProperties;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
import org.apache.log4j.Logger;

import java.io.*;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.List;

public class FtpClient {

    private static final Logger LOGGER = Logger.getLogger(FtpClient.class);

    //实际操作FTP服务的客户端类
    private FTPClient ftpClient = null;


    //构造  初始化
    public FtpClient(FTPProperties ftpProperties) {
        String ftpServer = ftpProperties.getServer();
        Integer port = ftpProperties.getPort();
        String user = ftpProperties.getUser();
        String pwd = ftpProperties.getPassword();
        ftpClient = new FTPClient();
        ftpClient.setControlEncoding("utf-8");
        try {
            ftpClient.connect(ftpServer, port); //连接ftp服务器
            ftpClient.login(user, pwd); //登录ftp服务器
            int replyCode = ftpClient.getReplyCode(); //是否成功登录服务器
            if (!FTPReply.isPositiveCompletion(replyCode)) {
                LOGGER.error("未能成功连接FTP服务器[" + ftpServer + ":" + port + "]");
                throw new IOException("不能连接FTP服务器 :" + ftpServer);
            }
            LOGGER.info("成功连接FTP服务器[" + ftpServer + ":" + port + "]");
            // set data transfer mode.
            ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
            // Use passive mode to pass firewalls.
            ftpClient.enterLocalPassiveMode();
        } catch (MalformedURLException e) {
            LOGGER.error("FTP服务器地址错误:" + ftpServer);
        } catch (IOException e) {
            LOGGER.error("登录FTP服务器[" + ftpServer + ":" + port + "]出现错误" + e);
        }
    }

    //构造  初始化
    public FtpClient(String ftpServer,Integer port,String user,String pwd) {
        ftpClient = new FTPClient();
        ftpClient.setControlEncoding("utf-8");
        try {
            ftpClient.connect(ftpServer, port); //连接ftp服务器
            ftpClient.login(user, pwd); //登录ftp服务器
            int replyCode = ftpClient.getReplyCode(); //是否成功登录服务器
            if (!FTPReply.isPositiveCompletion(replyCode)) {
                LOGGER.error("未能成功连接FTP服务器[" + ftpServer + ":" + port + "]");
                throw new IOException("不能连接FTP服务器 :" + ftpServer);
            }
            LOGGER.info("成功连接FTP服务器[" + ftpServer + ":" + port + "]");
            // set data transfer mode.
            ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
            // Use passive mode to pass firewalls.
            ftpClient.enterLocalPassiveMode();
        } catch (MalformedURLException e) {
            LOGGER.error("FTP服务器地址错误:" + ftpServer);
        } catch (IOException e) {
            LOGGER.error("登录FTP服务器[" + ftpServer + ":" + port + "]出现错误" + e);
        }
    }

    //设置超时时间
    public void setTimeout(int defaultTimeout, int connectTimeout, int dataTimeout) {
        ftpClient.setDefaultTimeout(defaultTimeout);
        ftpClient.setConnectTimeout(connectTimeout);
        ftpClient.setDataTimeout(dataTimeout);
    }


    /**
      * 方法描述 上传文件
      * @method upload
      * @param localFile 本地文件对象
      * @param ftpFileName FTP服务器文件地址
      */
    private void upload(File localFile, String ftpFileName) throws IOException {
        if (!localFile.exists()) {
            throw new IOException("Can't upload '" + localFile.getAbsolutePath() + "'. This file doesn't exist.");
        }
        InputStream in = null;
        try {
            in = new BufferedInputStream(new FileInputStream(localFile));
            if (!ftpClient.storeFile(ftpFileName, in)) {
                throw new IOException("Can't upload file '" + ftpFileName + "' to FTP server. Check FTP permissions and path.");
            }
            LOGGER.info("文件" + ftpFileName + "上传成功");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            in.close();
        }

    }


    /**
      * 方法描述 上传文件
      * @method upload
      * @param localFilePath 本地文件路径
      * @param ftpFileName FTP服务器文件地址
      */
    public void upload(String localFilePath, String ftpFileName) throws IOException {
        File file = new File(localFilePath);
        upload(file, ftpFileName);
    }



    /**
      * 方法描述 上次文件到FTP服务器的指定目录
      * @method upload2Dir
      * @param localFilePath 本地文件路径
      * @param remoteDir FTP服务器中的目录路径
      */
    public void upload2Dir(String localFilePath, String remoteDir) throws IOException {
        createDir(remoteDir);
        File localFile = new File(localFilePath);
        upload(localFile, remoteDir + "/" + localFile.getName());
    }


    /**
     * 方法描述 上次文件到FTP服务器的指定目录
     * @method upload2Dir
     * @param localFilePath 本地文件路径
     * @param remoteDir FTP服务器中的目录路径
     * @param remoteFileName FTP服务器中的文件名
     */
    public void upload2Dir(String localFilePath, String remoteDir, String remoteFileName) throws IOException {
        createDir(remoteDir);
        File localFile = new File(localFilePath);
        upload(localFile, remoteDir + "/" + remoteFileName);
    }


    /**
      * 方法描述 创建FTP目录
      * @method createDir
      * @param remoteDir FTP服务器中目录字符串
      */
    private void createDir(String remoteDir) throws IOException {
        if (!ftpClient.changeWorkingDirectory(remoteDir)) {
            String[] paths = remoteDir.split("/");
            StringBuffer dirBuffer = new StringBuffer();
            for (int index = 1; index < paths.length; index++) {
                dirBuffer.append("/");
                dirBuffer.append(paths[index]);
                String dirName = dirBuffer.toString();
                if (ftpClient.changeWorkingDirectory(dirName)) {
                    continue;
                } else {
                    ftpClient.makeDirectory(dirName);
                    LOGGER.info("创建目录" + dirName + "成功");
                    ftpClient.changeWorkingDirectory(dirName);
                }
            }
        }
    }


    /**
      * 方法描述 上次目录到FTP服务器
      * @method uploadDir
      * @param localPath 本地文件路径
      * @param remotePath FTP服务器目录路径
      */
    public void uploadDir(String localPath, String remotePath) throws IOException {
        localPath = localPath.replace("\\\\", "/");
        File file = new File(localPath);
        if (file.exists()) {
            if (!ftpClient.changeWorkingDirectory(remotePath)) {
                if (ftpClient.makeDirectory(remotePath)) {
                    LOGGER.info("创建目录" + remotePath + "成功");
                }
                ftpClient.changeWorkingDirectory(remotePath);
            }
            File[] files = file.listFiles();
            if (null != files) {
                for (File f : files) {
                    if (f.isDirectory() && !f.getName().equals(".") && !f.getName().equals("..")) {
                        uploadDir(f.getPath(), remotePath + "/" + f.getName());
                    } else if (f.isFile()) {
                        upload(f, remotePath + "/" + f.getName());
                    }
                }
            }
        }
    }


    /**   
      * 方法描述 
      * @method 下载文件
      * @param ftpFileName FTP服务器中的文件路径
      * @param localFilePath 本地文件保存路径
      */
    public void download(String ftpFileName, String localFilePath) throws IOException {
        OutputStream out = null;
        File localFile = new File(localFilePath);
        try {
            FTPFile[] fileInfoArray = ftpClient.listFiles(ftpFileName);
            if (fileInfoArray == null || fileInfoArray.length == 0) {
                throw new FileNotFoundException("File " + ftpFileName + " was not found on FTP server.");
            }

            FTPFile fileInfo = fileInfoArray[0];
            if (fileInfo.getSize() > Integer.MAX_VALUE) {
                throw new IOException("File " + ftpFileName + " is too large.");
            }

            out = new BufferedOutputStream(new FileOutputStream(localFile));
            if (!ftpClient.retrieveFile(ftpFileName, out)) {
                throw new IOException("Error loading file " + ftpFileName + " from FTP server. Check FTP permissions and path.");
            }
            out.flush();
            LOGGER.info("文件" + ftpFileName + "下载成功:" + localFilePath);
        } catch (IOException e) {
            LOGGER.error("文件下载出现错误" + e);
        } finally {
            out.close();
        }
    }

    /**   
      * 方法描述 
      * @method 下载FTP服务器中的指定目录
      * @param remotePath FTP服务器中的被下载目录路径
      * @param localPath 本地保存目录的路径
      */
    public void downloadDir(String remotePath, String localPath) throws IOException {
        localPath = localPath.replace("\\\\", "/");
        File file = new File(localPath);
        if (!file.exists()) {
            file.mkdirs();
        }
        FTPFile[] ftpFiles = ftpClient.listFiles(remotePath);
        for (int i = 0; ftpFiles != null && i < ftpFiles.length; i++) {
            FTPFile ftpFile = ftpFiles[i];
            if (ftpFile.isDirectory() && !ftpFile.getName().equals(".") && !ftpFile.getName().equals("..")) {
                downloadDir(remotePath + "/" + ftpFile.getName(), localPath + "/" + ftpFile.getName());
            } else {
                download(remotePath + "/" + ftpFile.getName(), localPath + "/" + ftpFile.getName());
            }
        }
    }


    /**   
      * 方法描述 删除FTP服务器中的指定的目录
      * @method deleteDir
      * @param remoteDir 被删除目录的路径
      */
    public void deleteDir(String remoteDir) throws IOException {
        FTPFile[] ftpFiles = ftpClient.listFiles(remoteDir);
        if (ftpFiles.length > 0) {
            for (int i = 0; i < ftpFiles.length; i++) {
                FTPFile ftpFile = ftpFiles[i];
                String name = ftpFile.getName();
                if (ftpFile.isDirectory()) {
                    deleteDir(remoteDir + "/" + ftpFile.getName());
                } else {
                    deleteFile(remoteDir + "/" + name);
                }
            }
            deleteDir(remoteDir);
        } else {
            if (!ftpClient.removeDirectory(remoteDir)) {
                throw new IOException("Can't remove folder '" + remoteDir + "' from FTP server.");
            }
            LOGGER.info("删除目录" + remoteDir + "成功");
        }

    }

    /**
      * 方法描述 删除FTP服务器中指定的文件
      * @method deleteFile
      * @param ftpFileName 被删除文件的路径
      */
    public void deleteFile(String ftpFileName) throws IOException {
        if (!ftpClient.deleteFile(ftpFileName)) {
            throw new IOException("Can't remove file '" + ftpFileName + "' from FTP server.");
        }
        LOGGER.info("删除文件" + ftpFileName + "成功");
    }


    /**
      * 方法描述 获取ftp服务器指定目录中的文件名称列表
      * @method list
      * @param remotePath 远程目录
      * @return List<String> 文件名称列表
      */
    public List<String> list(String remotePath) throws IOException {
        ftpClient.changeWorkingDirectory(remotePath);
        List<String> fileNames = new ArrayList<String>();
        FTPFile[] ftpFiles = ftpClient.listFiles();
        for (FTPFile ftpFile : ftpFiles) {
            String fileName = ftpFile.getName();
            fileNames.add(fileName);
        }
        return fileNames;
    }





    /**
      * 方法描述 断开FTP服务器连接
      * @method disconnect
      */
    public void disconnect() {
        if (null != ftpClient && ftpClient.isConnected()) {
            try {
                ftpClient.logout();
                ftpClient.disconnect();
                LOGGER.info("FTP服务器连接关闭");
            } catch (IOException ex) {
                LOGGER.error("关闭FTP服务器错误");
            }
        }
    }
}



引用Starter

使用 maven install 将项目打包到maven仓库或maven远程中心仓库

然后直接使用dependency 引用FTP Starter的groupId和artifactId即可。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值