SpringBoot整合自定义FTP文件连接池

SpringBoot整合自定义FTP文件连接池

说明:通过GenericObjectPool实现的FTP连接池,记录一下以供以后使用
环境:
JDK版本1.8
框架 :springboot2.1
文件服务器: Serv-U
1.引入依赖

        <!--ftp文件上传-->
        <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>

2.创建ftp.properties

ftp.Host=192.168.xx.xx    本机ip
ftp.Port=21
ftp.UserName=root
ftp.PassWord=root
ftp.workDir=/images
ftp.encoding=utf-8
ftp.root=/
ftp.MaxTotal=100  
ftp.MinIdel=2
ftp.MaxIdle=5
ftp.MaxWaitMillis=3000

3.创建配置类FtpConfig

package com.hcq.demo.util;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * fileName:FtpConfig
 * description:
 * author:hcq
 * createTime:2019-03-15 15:04
 */

@Component
@ConfigurationProperties(prefix="ftp")
@PropertySource("classpath:ftp.properties")
public class FtpConfig {
     private String Host;
     private int Port;
     private String UserName;
     private String PassWord;
     private String workDir;
     private String encoding;
     private String root;
     private int MaxTotal;
     private int MinIdel;
     private int MaxIdle;
     private int MaxWaitMillis;
     .......省略get set
}

4.创建FtpClientFactory工厂类

package com.hcq.demo.util;

import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.impl.DefaultPooledObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.apache.commons.pool2.PooledObjectFactory;

import java.io.IOException;

/**
 * fileName:FtpClientFactory
 * description:
 * author:hcq
 * createTime:2019-03-18 19:49
 */
@Component
public class FtpClientFactory implements PooledObjectFactory<FTPClient> {
    @Autowired
    FtpConfig config;
    //创建连接到池中
    @Override
    public PooledObject<FTPClient> makeObject() {
            FTPClient ftpClient = new FTPClient();//创建客户端实例
            return new DefaultPooledObject<>(ftpClient);
    }
    //销毁连接,当连接池空闲数量达到上限时,调用此方法销毁连接
    @Override
    public void destroyObject(PooledObject<FTPClient> pooledObject)  {
        FTPClient ftpClient = pooledObject.getObject();
        try {
            ftpClient.logout();
            if (ftpClient.isConnected()) {
                ftpClient.disconnect();
            }
        } catch (IOException e) {
            throw new RuntimeException("Could not disconnect from server.", e);
        }
    }
    //链接状态检查
    @Override
    public boolean validateObject(PooledObject<FTPClient> pooledObject) {
        FTPClient ftpClient = pooledObject.getObject();
        try {
            return ftpClient.sendNoOp();
        } catch (IOException e) {
            return false;
        }
    }
    //初始化连接
    @Override
    public void activateObject(PooledObject<FTPClient> pooledObject) throws Exception {
        FTPClient ftpClient = pooledObject.getObject();
        ftpClient.connect(config.getHost(),config.getPort());
        ftpClient.login(config.getUserName(), config.getPassWord());
        ftpClient.setControlEncoding(config.getEncoding());
        ftpClient.changeWorkingDirectory(config.getWorkDir());
        ftpClient.setFileType(FTP.BINARY_FILE_TYPE);//设置上传文件类型为二进制,否则将无法打开文件
    }
    //钝化连接,使链接变为可用状态
    @Override
    public void passivateObject(PooledObject<FTPClient> pooledObject) throws Exception {
        FTPClient ftpClient = pooledObject.getObject();
        try {
            ftpClient.changeWorkingDirectory(config.getRoot());
            ftpClient.logout();
            if (ftpClient.isConnected()) {
                ftpClient.disconnect();
            }
        } catch (IOException e) {
            throw new RuntimeException("Could not disconnect from server.", e);
        }
    }
    //用于连接池中获取pool属性
    public FtpConfig getConfig() {
        return config;
    }
}

5.创建FtpPool连接池

package com.hcq.demo.util;

import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;


/**
 * fileName:ftpPool
 * description:FTP连接池
 *            1.可以获取池中空闲链接
 *            2.可以将链接归还到池中
 *            3.当池中空闲链接不足时,可以创建链接
 * author:hcq
 * createTime:2019-03-16 9:59
 */
@Component
public class FtpPool {
    FtpClientFactory factory;
    private final GenericObjectPool<FTPClient> internalPool;
    //初始化连接池
    public FtpPool(@Autowired FtpClientFactory factory){
        this.factory=factory;
        FtpConfig config = factory.getConfig();
        GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
        poolConfig.setMaxTotal(config.getMaxTotal());
        poolConfig.setMinIdle(config.getMinIdel());
        poolConfig.setMaxIdle(config.getMaxIdle());
        poolConfig.setMaxWaitMillis(config.getMaxWaitMillis());
        this.internalPool = new GenericObjectPool<FTPClient>(factory,poolConfig);
    }
    //从连接池中取连接
    public  FTPClient getFTPClient() {
        try {
            return internalPool.borrowObject();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
    //将链接归还到连接池
    public  void returnFTPClient(FTPClient ftpClient) {
        try {
            internalPool.returnObject(ftpClient);
        } catch (Exception e) {
             e.printStackTrace();
        }
    }
    /**
     * 销毁池子
     */
    public  void destroy() {
        try {
            internalPool.close();
        } catch (Exception e) {
          e.printStackTrace();
        }
    }
}

6.创建FtpUtil类

package com.hcq.demo.util;

import org.apache.commons.net.ftp.FTPClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ResourceLoader;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.UUID;

/**
 * fileName:FTP工具类
 * description:提供文件上传和下载
 * author:hcq
 * createTime:2019-03-16 8:55
 */
@Component
public class FtpUtil {
    @Autowired
    FtpConfig config;
    @Autowired
    private ResourceLoader resourceLoader;
    @Autowired
    FtpPool pool;
    /**
     * Description: 向FTP服务器上传文件
     *
     * @Version2.0
     * @param file
     *            上传到FTP服务器上的文件
     * @return
     *           成功返回文件名,否则返回null
     */
    public  String upload(MultipartFile file) throws Exception {
        FTPClient ftpClient = pool.getFTPClient();
            //开始进行文件上传
            String fileName=UUID.randomUUID()+file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
            InputStream input=file.getInputStream();
            try {
                boolean result=ftpClient.storeFile(fileName,input);//执行文件传输
                if(!result){//上传失败
                    throw new RuntimeException("上传失败");
                }
            }catch(Exception e){
                e.printStackTrace();
                return null;
            }finally {//关闭资源
                input.close();
                System.out.println("开始归还连接");
                pool.returnFTPClient(ftpClient);//归还资源
            }
            return fileName;
    }
    /**
     * Description: 从FTP服务器下载文件
     *
     * @Version1.0
     * @param fileName
     *        FTP服务器中的文件名
     * @param resp
     *        响应客户的响应体
     */
    public  void downLoad(String fileName,HttpServletResponse resp) throws IOException {
            FTPClient ftpClient = pool.getFTPClient();
            resp.setContentType("application/force-download");// 设置强制下载不打开 MIME
            resp.addHeader("Content-Disposition", "attachment;fileName="+fileName);// 设置文件名
            //将文件直接读取到响应体中
            OutputStream out = resp.getOutputStream();
            ftpClient.retrieveFile(config.getWorkDir()+"/"+fileName, out);
            out.flush();
            out.close();
            pool.returnFTPClient(ftpClient);
    }
    /**
     * Description: 从FTP服务器读取图片
     *
     * @Version1.0
     * @param fileName
     *        需要读取的文件名
     * @return
     *        返回文件对应的Entity
     */
    public ResponseEntity show(String fileName){
        String username=config.getUserName();
        String password=config.getPassWord();
        String host=config.getHost();
        String work=config.getWorkDir();
          //ftp://root:root@192.168.xx.xx/+fileName
        return ResponseEntity.ok(resourceLoader.getResource("ftp://"+username+":"+password+"@"+host+work+"/"+fileName));
    }


}
  • 3
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

敲得码黛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值