• 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));
    }


    }
    ---------------------
    作者:Keepalived。
    来源:CSDN
    原文:https://blog.csdn.net/qq_39914581/article/details/88660133
    版权声明:本文为博主原创文章,转载请附上博文链接!

  • 相关阅读:
    LaTeX —— 特殊符号与数学字体
    LaTeX —— 特殊符号与数学字体
    实战caffe多标签分类——汽车品牌与车辆外观(C++接口)[详细实现+数据集]
    家书与家训
    家书与家训
    Handler总结
    (step5.1.3)hdu 1213( How Many Tables——1213)
    JavaScript+XML+VBA导出报表初步构想
    XML学习总结
    JSP 9 大内置对象详解
  • 原文地址:https://www.cnblogs.com/pangguoming/p/10910655.html
Copyright © 2020-2023  润新知