java ftp 连接池

Ftp连接池

maven引入,主要引入ftp的包和连接池的包 其他默认使用spring的包。

       <dependency>
            <groupId>commons-net</groupId>
            <artifactId>commons-net</artifactId>
            <version>3.3</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
            <version>2.4.2</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

FTPConfiguration


import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.pool2.ObjectPool;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.PooledObjectFactory;
import org.apache.commons.pool2.impl.DefaultPooledObject;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PreDestroy;

@Slf4j
@Configuration
@ConditionalOnClass({GenericObjectPool.class, FTPClient.class})
@EnableConfigurationProperties(FTPConfiguration.FtpConfigProperties.class)
public class FTPConfiguration {

    private ObjectPool<FTPClient> pool;

    public FTPConfiguration(FtpConfigProperties props) {
        // 默认最大连接数与最大空闲连接数都为8,最小空闲连接数为0
        // 其他未设置属性使用默认值,可根据需要添加相关配置
        GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
        poolConfig.setTestOnBorrow(true);
        poolConfig.setTestOnReturn(true);
        poolConfig.setTestWhileIdle(true);
        poolConfig.setMinEvictableIdleTimeMillis(60000);
        poolConfig.setSoftMinEvictableIdleTimeMillis(50000);
        poolConfig.setTimeBetweenEvictionRunsMillis(30000);
        pool = new GenericObjectPool<>(new FtpClientPooledObjectFactory(props), poolConfig);
        preLoadingFtpClient(props.getInitialSize(), poolConfig.getMaxIdle());
        // 初始化ftp工具类中的ftpClientPool
        FtpUtils.init(pool);
    }

    /**
     * 预先加载FTPClient连接到对象池中
     * @param initialSize 初始化连接数
     * @param maxIdle 最大空闲连接数
     */
    private void preLoadingFtpClient(Integer initialSize, int maxIdle) {
        if (initialSize == null || initialSize <= 0) {
            return;
        }
        int size = Math.min(initialSize.intValue(), maxIdle);
        for (int i = 0; i < size; i++) {
            try {
                pool.addObject();
            } catch (Exception e) {
                log.error("preLoadingFtpClient error...", e);
            }
        }
    }

    @PreDestroy
    public void destroy() {
        if (pool != null) {
            pool.close();
            log.info("销毁ftpClientPool...");
        }
    }

    /**
     * Ftp配置属性类,建立ftpClient时使用
     */
    @Data
    @ConfigurationProperties(prefix = "ftp")
    static class FtpConfigProperties {

        private String host;

        private int port;

        private String username;

        private String password;

        private int bufferSize = 8096;

        private String encoding;

        /**
         * 初始化连接数
         */
        private Integer initialSize = 0;

    }

    /**
     * FtpClient对象工厂类
     */
    static class FtpClientPooledObjectFactory implements PooledObjectFactory<FTPClient> {

        private FtpConfigProperties props;

        public FtpClientPooledObjectFactory(FtpConfigProperties props) {
            this.props = props;
        }

        @Override
        public PooledObject<FTPClient> makeObject() throws Exception {
            FTPClient ftpClient = new FTPClient();
            try {
                ftpClient.connect(props.getHost(), props.getPort());
                ftpClient.login(props.getUsername(), props.getPassword());
                log.debug("连接FTP服务器返回码{}", ftpClient.getReplyCode());
                ftpClient.setBufferSize(props.getBufferSize());
                //ftpClient.setControlEncoding(props.getEncoding());
                ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
                // ftpClient.enterLocalPassiveMode();
                return new DefaultPooledObject<>(ftpClient);
            } catch (Exception e) {
                log.error("建立FTP连接失败", e);
                if (ftpClient.isAvailable()) {
                    ftpClient.disconnect();
                }
                throw new Exception("建立FTP连接失败", e);
            }
        }

        @Override
        public void destroyObject(PooledObject<FTPClient> p) throws Exception {
            FTPClient ftpClient = getObject(p);
            if (ftpClient != null && ftpClient.isConnected()) {
                ftpClient.disconnect();
            }
        }

        @Override
        public boolean validateObject(PooledObject<FTPClient> p) {
            FTPClient ftpClient = getObject(p);
            if (ftpClient == null || !ftpClient.isConnected()) {
                return false;
            }
            try {
                ftpClient.changeWorkingDirectory("/");
                return true;
            } catch (Exception e) {
                log.error("验证FTP连接失败::{}", e);
                return false;
            }
        }

        @Override
        public void activateObject(PooledObject<FTPClient> p) throws Exception {
        }

        @Override
        public void passivateObject(PooledObject<FTPClient> p) throws Exception {
        }

        private FTPClient getObject(PooledObject<FTPClient> p) {
            if (p == null || p.getObject() == null) {
                return null;
            }
            return p.getObject();
        }

    }

import lombok.extern.slf4j.Slf4j;
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.pool2.ObjectPool;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

import java.io.*;

@Slf4j
@Component
public class FtpUtils {

    /**
     * ftpClient连接池初始化标志
     */
    private static volatile boolean hasInit = false;
    /**
     * ftpClient连接池
     */
    private static ObjectPool<FTPClient> ftpClientPool;


    private static String encoding;

    @Value("${ftp.encoding}")
    public void setEncoding(String encoding) {
        FtpUtils.encoding = encoding;
    }

    public static void init(ObjectPool<FTPClient> ftpClientPool) {
        if (!hasInit) {
            synchronized (FtpUtils.class) {
                if (!hasInit) {
                    FtpUtils.ftpClientPool = ftpClientPool;
                    hasInit = true;
                }
            }
        }
    }

    private static FTPClient getFtpClient() {
        checkFtpClientPoolAvailable();
        FTPClient ftpClient = null;
        Exception ex = null;
        for (int i = 0; i < 3; i++) {
            try {
                ftpClient = ftpClientPool.borrowObject();
                ftpClient.changeWorkingDirectory("/");
                break;
            } catch (Exception e) {
                ex = e;
            }
        }
        if (ftpClient == null) {
            throw new RuntimeException("Could not get a ftpClient from the pool", ex);
        }
        return ftpClient;
    }

    public static String[] retrieveFTPFiles(String remotePath) throws IOException {
        FTPClient ftpClient = getFtpClient();
        try {
            ftpClient.setControlEncoding(encoding);
            ftpClient.changeWorkingDirectory(remotePath);
            return ftpClient.listNames();
        } finally {
            releaseFtpClient(ftpClient);
        }
    }

    public static FTPFile[] getFTPFiles() throws IOException {
        FTPClient ftpClient = getFtpClient();
        try {
            return ftpClient.listFiles();
        } finally {
            releaseFtpClient(ftpClient);
        }
    }


    public static void deleteFTPFiles(String path,String remotePath){
        FTPClient ftpClient = getFtpClient();
        try {
            ftpClient.changeWorkingDirectory(path);
            ftpClient.deleteFile(new String(remotePath.getBytes(encoding),"ISO-8859-1"));
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            releaseFtpClient(ftpClient);
        }
    }
  
    public static void deleteFTPFiles(String remotePath,FTPClient ftpClient){
        try {
            ftpClient.deleteFile(new String(remotePath.getBytes(encoding),"ISO-8859-1"));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    private static void releaseFtpClient(FTPClient ftpClient) {
        if (ftpClient == null) {
            return;
        }

        try {
            ftpClientPool.returnObject(ftpClient);
        } catch (Exception e) {
            log.error("Could not return the ftpClient to the pool", e);
            // destoryFtpClient
            if (ftpClient.isAvailable()) {
                try {
                    ftpClient.disconnect();
                } catch (IOException io) {
                }
            }
        }
    }


    public static byte[] getFileBytesByName(String ftpPath, String fileName) {
        // 登录
        FTPClient ftpClient = getFtpClient();
        //创建byte数组输出流
        ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
        try {
            ftpClient.changeWorkingDirectory(ftpPath);
            InputStream is = ftpClient.retrieveFileStream(new String(fileName.getBytes(encoding),"ISO-8859-1"));
            byte[] buffer = new byte[1024 * 1024 * 4];
            int len = -1;
            while ((len = is.read(buffer, 0, 1024 * 1024 * 4)) != -1) {
                byteStream.write(buffer, 0, len);
            }
            is.close();
            ftpClient.completePendingCommand();
        }catch (Exception e){
            log.error(e.getMessage(), e);
        }finally {
            releaseFtpClient(ftpClient);
        }
        return byteStream.toByteArray();
    }


    public static void upload(String path,File f){

        FTPClient ftp = getFtpClient();
        try {
            ftp.changeWorkingDirectory(path);
            ftp.setFileType(FTP.BINARY_FILE_TYPE);
            InputStream input = new FileInputStream(f);
            ftp.storeFile(new String(f.getName().getBytes(encoding),"ISO-8859-1"),input);
            input.close();
        } catch (FileNotFoundException fileNotFoundException) {
            fileNotFoundException.printStackTrace();
        } catch (IOException ioException) {
            ioException.printStackTrace();
        }finally {
            releaseFtpClient(ftp);
        }

    }

    public static void downloadFiles(String ftpPath, String savePath) {

        FTPClient ftpClient = getFtpClient();
        try {
            // 判断是否存在该目录
            if (!ftpClient.changeWorkingDirectory(ftpPath)) {
                return;
            }
            ftpClient.enterLocalPassiveMode();  // 设置被动模式,开通一个端口来传输数据
            String[] fs = ftpClient.listNames();
            // 判断该目录下是否有文件
            if (fs == null || fs.length == 0) {
                return;
            }
            File files = new File(savePath);
            if(!files.exists()){
                files.mkdir();
            }
            for (String ff : fs) {
                //String ftpName = new String(ff.getBytes("UTF-8"),encoding);
                File file = new File(savePath + '/' + ff);
                try (OutputStream os = new FileOutputStream(file)) {
                    ftpClient.retrieveFile(ff, os);
                } catch (Exception e) {
                    log.error(e.getMessage(), e);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            releaseFtpClient(ftpClient);
        }
    }


    private static void checkFtpClientPoolAvailable() {
        Assert.state(hasInit, "FTP未启用或连接失败!");
    }
}


配置文件

ftp.host=127.0.0.1
ftp.port=21
ftp.username=ftpTest
ftp.password=123456
#ftp服务编码,默认为GBK
ftp.encoding =GBK
#ftp 文件路径 默认为根目录
ftp.path = \\
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值