原文: https://blog.csdn.net/qq_35433926/article/details/91880345

springboot2.1.3配置sftp,自定义sftp连接池

 

项目地址

项目地址:https://gitee.com/xuelingkang/spring-boot-demo
完整配置参考com.example.ftp包

maven: 

<!-- sftp -->
<dependency>
    <groupId>com.jcraft</groupId>
    <artifactId>jsch</artifactId>
    <version>0.1.56</version>
</dependency>
<!-- commons-pool2 -->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
    <version>2.11.1</version>
</dependency>

 

commons-pool2 配置详解: https://www.jianshu.com/p/e9194bd84e38

application.yml配置

sftp:
  host: server02 # 服务器ip
  port: 22 # ssh端口
  username: demofile # 用户名
  password: demo # 密码
  # 连接池参数
  pool:
    max-total: 10
    max-idle: 10
    min-idle: 5

or application.properties

sftp.username = root
sftp.password = root
sftp.host = 192.168.80.51
sftp.port = 2222
sftp.pool.max-total = 10
sftp.pool.max-idle = 10
sftp.pool.min-idle = 3
sftp.poll.maxWaitMillis = 60000

 

SftpProperties

package com.example.ftp;

import com.jcraft.jsch.ChannelSftp;
import lombok.Data;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.boot.context.properties.ConfigurationProperties;

@Data
@ConfigurationProperties(prefix = "sftp")
public class SftpProperties {

    private String host;
    private int port = 22;
    private String username = "root";
    private String password = "root";
    private Pool pool = new Pool();

    public static class Pool extends GenericObjectPoolConfig<ChannelSftp> {

        private int maxTotal = DEFAULT_MAX_TOTAL;
        private int maxIdle = DEFAULT_MAX_IDLE;
        private int minIdle = DEFAULT_MIN_IDLE;

        public Pool() {
            super();
        }
        @Override
        public int getMaxTotal() {
            return maxTotal;
        }
        @Override
        public void setMaxTotal(int maxTotal) {
            this.maxTotal = maxTotal;
        }
        @Override
        public int getMaxIdle() {
            return maxIdle;
        }
        @Override
        public void setMaxIdle(int maxIdle) {
            this.maxIdle = maxIdle;
        }
        @Override
        public int getMinIdle() {
            return minIdle;
        }
        @Override
        public void setMinIdle(int minIdle) {
            this.minIdle = minIdle;
        }

    }

}

sftp连接工厂

package com.example.ftp;
import com.example.exception.ProjectException;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.pool2.BasePooledObjectFactory;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.impl.DefaultPooledObject;

import java.util.Properties;

@Data
@Slf4j
public class SftpFactory extends BasePooledObjectFactory<ChannelSftp> {

    private SftpProperties properties;

    public SftpFactory(SftpProperties properties) {
        this.properties = properties;
    }

    @Override
    public ChannelSftp create() {
        try {
            JSch jsch = new JSch();
            Session sshSession = jsch.getSession(properties.getUsername(), properties.getHost(), properties.getPort());
            sshSession.setPassword(properties.getPassword());
            Properties sshConfig = new Properties();
            sshConfig.put("StrictHostKeyChecking", "no");
            sshSession.setConfig(sshConfig);
            sshSession.connect();
            ChannelSftp channel = (ChannelSftp) sshSession.openChannel("sftp");
            channel.connect();
            return channel;
        } catch (JSchException e) {
            throw new ProjectException("连接sfpt失败", e);
        }
    }

    @Override
    public PooledObject<ChannelSftp> wrap(ChannelSftp channelSftp) {
        return new DefaultPooledObject<>(channelSftp);
    }

    // 销毁对象
    @Override
    public void destroyObject(PooledObject<ChannelSftp> p) {
        ChannelSftp channelSftp = p.getObject();
        channelSftp.disconnect();
    }

}

sftp连接池

package com.example.ftp;

import com.example.exception.ProjectException;
import com.jcraft.jsch.ChannelSftp;
import lombok.Data;
import org.apache.commons.pool2.impl.GenericObjectPool;

@Data
public class SftpPool {

    private GenericObjectPool<ChannelSftp> pool;

    public SftpPool(SftpFactory factory) {
        this.pool = new GenericObjectPool<>(factory, factory.getProperties().getPool());
    }

    /**
     * 获取一个sftp连接对象
     * @return sftp连接对象
     */
    public ChannelSftp borrowObject() {
        try {
            return pool.borrowObject();
        } catch (Exception e) {
            throw new ProjectException("获取ftp连接失败", e);
        }
    }

    /**
     * 归还一个sftp连接对象
     * @param channelSftp sftp连接对象
     */
    public void returnObject(ChannelSftp channelSftp) {
        if (channelSftp!=null) {
            pool.returnObject(channelSftp);
        }
    }

}

sftptemplate 辅助类

import com.icil.bx.common.config.SftpPool;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.SftpException;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.Vector;

/**
 * @PACKAGE : com.icil.bx.common.utils
 * @Author :  Sea
 * @Date : 8/23/21 9:31 AM
 * @Desc :
 **/
public class SFTPTemplate {
    private transient Logger log = LoggerFactory.getLogger(this.getClass());
    //结合springboot
    private SftpPool pool;

    public SFTPTemplate(SftpPool pool) {
        this.pool = pool;
    }

    /**
     * 将输入流的数据上传到sftp作为文件。文件完整路径=basePath+directory
     * @param basePath  服务器的基础路径 eg: /upload
     * @param directory  上传到该目录 eg:  img/  or img/cc/   一定要带上最后的URL,否则返回的url无效
     * @param sftpFileName  sftp端文件名   eg : xx.png
     * @param input   输入流
     */
    public String upload(String basePath,String directory, String sftpFileName, InputStream input) throws Exception {
        ChannelSftp sftp = pool.borrowObject();
        try{
              log.info("start upload file {}",sftpFileName);
               mkdir(basePath,directory,sftp);
               sftp.put(input, sftpFileName);  //上传文件
               log.info("end upload file {}",sftpFileName);
           } catch (Exception e)
           {
               throw new Exception(e.getMessage());
           }finally
           {
               pool.returnObject(sftp);
           }
          return directory+sftpFileName;
    }


    private void mkdir(String basePath,String directory,ChannelSftp sftp) throws SftpException {
        try
        {
            sftp.cd(basePath);
            sftp.cd(directory);
        }
        catch (SftpException e)
        {
            log.info("目录不存在,创建文件夹");
            //目录不存在,则创建文件夹
            String [] dirs=directory.split("/");
            String tempPath=basePath;
            for(String dir:dirs)
            {
                if(null== dir || "".equals(dir)) continue;
                tempPath+="/"+dir;
                try{
                    sftp.cd(tempPath);
                }catch(SftpException ex){
                    sftp.mkdir(tempPath);
                    sftp.cd(tempPath);
                }
            }
        }
    }



    /**
     * 下载文件。
     * @param directory 下载目录
     * @param downloadFile 下载的文件
     * @param saveFile 存在本地的路径
     */
    public void download(String directory, String downloadFile, String saveFile) throws Exception{
        ChannelSftp sftp = pool.borrowObject();
        try{
            if (directory != null && !"".equals(directory)) {
                sftp.cd(directory);
            }
            File file = new File(saveFile);
            sftp.get(downloadFile, new FileOutputStream(file));
           } catch (Exception e)
           {
             throw  new Exception(e.getMessage());
           } finally
          {
              pool.returnObject(sftp);
          }
    }

    /**
     * 下载文件
     * @param directory 下载目录
     * @param downloadFile 下载的文件名
     * @return 字节数组
     */
    public byte[] download(String directory, String downloadFile) throws Exception{
        ChannelSftp sftp = pool.borrowObject();
        try
        {
            if (directory != null && !"".equals(directory)) {
                sftp.cd(directory);
            }
            InputStream is = sftp.get(downloadFile);
            return IOUtils.toByteArray(is);
        } catch (Exception e)
        {
            throw new Exception(e.getMessage());
        }finally
        {
            pool.returnObject(sftp);
        }
    }


    /**
     * 删除文件
     * @param directory 要删除文件所在目录
     * @param deleteFile 要删除的文件
     */
    public void delete(String directory, String deleteFile) throws Exception{
        ChannelSftp sftp = pool.borrowObject();
        try
        {
            sftp.cd(directory);
            sftp.rm(deleteFile);
        } catch (Exception e)
        {
            throw new Exception(e.getMessage());
        }finally
        {
            pool.returnObject(sftp);
        }
    }


    /**
     * 列出目录下的文件
     * @param directory 要列出的目录
     */
    public Vector<?> listFiles(String directory) throws Exception {
        ChannelSftp sftp = pool.borrowObject();
        try
        {
            return sftp.ls(directory);
        } catch (Exception e)
        {
            throw new Exception(e.getMessage());
        }finally
        {
            pool.returnObject(sftp);
        }
    }
}

 

 

主配置类

package com.example.config;

import com.example.ftp.SftpFactory;
import com.example.ftp.SftpHelper;
import com.example.ftp.SftpPool;
import com.example.ftp.SftpProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

// ftp配置
@Configuration
@EnableConfigurationProperties(SftpProperties.class)
public class SftpConfig {

    // 工厂
    @Bean
    public SftpFactory sftpFactory(SftpProperties properties) {
        return new SftpFactory(properties);
    }

    // 连接池
    @Bean
    public SftpPool sftpPool(SftpFactory sftpFactory) {
        return new SftpPool(sftpFactory);
    }

    // 辅助类
   @Bean
  public SFTPTemplate sftpTemplate(SftpPool sftpPool) {
  return new SFTPTemplate(sftpPool);
  }
 }

使用方法

@Autowired
private SftpTemplate sftpTemplate;

  注入辅助类,直接调用方法即可。

 


 

posted on 2021-08-24 14:54  lshan  阅读(1814)  评论(0编辑  收藏  举报