JSCH实现文件上传下载

前言

最近项目中经常用的jsch来进行文件上传下载,在业务量大的时候,每次都去获取sftp连接很消耗资源,后面就想着使用连接池来解决。

简述

1)jsch是ssh2的一个纯Java实现。它允许你连接到一个sshd服务器,使用端口转发、X11转发、文件传输等。
2)SSH 是较可靠,专为远程登录会话和其他网络服务提供安全性的协议。
3)ftp协议通常是用来在两个服务器之间传输文件的,但是它本质上是不安全的。
4)SFTP可以理解为SSH + FTP,也就是安全的网络文件传输协议。

Maven依赖

 <!-- sftp -->
        <dependency>
            <groupId>com.jcraft</groupId>
            <artifactId>jsch</artifactId>
            <version>0.1.55</version>
        </dependency>
        <!-- 连接池 -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>

application.yml配置文件

sftp:
  #服务器ip
  host: 192.168.xx.xx
  #ssh端口
  port: 22
  #用户名
  username: USER001
  #密码
  password: 123456
  #连接池参数
  pool:
    #对象池中管理的最多对象个数。默认值是8
    max-total: 10
    #对象池中最大的空闲对象个数。默认值是8
    max-idle: 10
    #对象池中最小的空闲对象个数。默认值是0
    min-idle: 5

连接池实现

public class SftpGenericObjectPool{

    private final GenericObjectPool<ChannelSftp> genericObjectPool;

    public SftpGenericObjectPool(SftpFactory sftpFactory, GenericObjectPoolConfig<ChannelSftp> sftpPoolConfig) {
        this.genericObjectPool = new GenericObjectPool<>(sftpFactory, sftpPoolConfig);
    }

    public ChannelSftp borrowObject() throws Exception {
        return genericObjectPool.borrowObject();
    }

    public void returnObject(ChannelSftp obj) {
        genericObjectPool.returnObject(obj);
    }
}

public class SftpFactory extends BasePooledObjectFactory<ChannelSftp> {
    @Value("${sftp.host}")
    private String host;
    @Value("${sftp.port}")
    private int port;
    @Value("${sftp.username}")
    private String username;
    @Value("${sftp.password}")
    private String password;

    @Override
    public ChannelSftp create() throws JSchException {
        JSch jsch = new JSch();
        Session sshSession = jsch.getSession(username, host, port);
        sshSession.setPassword(password);
        Properties sshConfig = new Properties();
        sshConfig.put("StrictHostKeyChecking", "no");
        sshSession.setConfig(sshConfig);
        sshSession.connect();
        ChannelSftp channel = (ChannelSftp) sshSession.openChannel("sftp");
        channel.connect();
        return channel;
    }

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

    /**
     * 销毁对象
     *
     * @param p
     * @return
     * @author fengfan
     * @date 2022/1/14 15:26
     */
    @Override
    public void destroyObject(PooledObject<ChannelSftp> p) {
        ChannelSftp channelSftp = p.getObject();
        channelSftp.disconnect();
    }

    /**
     * 激活连接池里面的sftp连接
     *
     * @param p
     * @throws Exception
     */
    @Override
    public void activateObject(PooledObject<ChannelSftp> p) throws Exception {
        ChannelSftp channelSftp = p.getObject();
        if(!channelSftp.isConnected()){
            channelSftp.connect();
        }

    }
}

Sftp工具类

public class SftpUtil {
    //连接池
    private SftpGenericObjectPool pool;

    public SftpUtil(SftpGenericObjectPool pool) {
        this.pool = pool;
    }

    /**
     * 下载文件
     *
     * @param dir  远程目录
     * @param name 远程文件名
     * @return 文件字节数组
     */
    public InputStream download(String dir, String name) throws Exception {
        ChannelSftp sftp = pool.borrowObject();
        try {
            sftp.cd(dir);
            return sftp.get(name);
        } finally {
            pool.returnObject(sftp);
        }
    }

    /**
     * 上传文件
     *
     * @param dir  远程目录
     * @param name 远程文件名
     * @param in   输入流
     */
    public void upload(String dir, String name, InputStream in) throws Exception {
        ChannelSftp sftp = pool.borrowObject();
        try {
            mkdirs(sftp, dir);
            sftp.cd(dir);
            sftp.put(in, name);
        } finally {
            pool.returnObject(sftp);
        }
    }

    /**
     * 删除文件
     *
     * @param dir  远程目录
     * @param name 远程文件名
     */
    public void delete(String dir, String name) throws Exception {
        ChannelSftp sftp = pool.borrowObject();
        try {
            sftp.cd(dir);
            sftp.rm(name);
        } finally {
            pool.returnObject(sftp);
        }
    }

    /**
     * 递归创建多级目录
     *
     * @param dir 多级目录
     */
    private void mkdirs(ChannelSftp sftp, String dir) throws SftpException {
        String[] folders = dir.split("/");
        sftp.cd("/");
        for (String folder : folders) {
            if (folder.length() > 0) {
                try {
                    sftp.cd(folder);
                } catch (Exception e) {
                    sftp.mkdir(folder);
                    sftp.cd(folder);
                }
            }
        }
    }

    public SftpGenericObjectPool getPool() {
        return pool;
    }

    public void setPool(SftpGenericObjectPool pool) {
        this.pool = pool;
    }
}

配置成Bean

@Configuration
public class SftpConfig {

    /**
     * 工厂
     *
     * @author fengfan
     * @date 2022/1/14 14:37
     * @return
     */
    @Bean
    public SftpFactory sftpFactory() {
        return new SftpFactory();
    }

    @Bean
    @ConfigurationProperties(prefix = "sftp.pool")
    public GenericObjectPoolConfig<ChannelSftp> sftpPoolConfig(){
        return new GenericObjectPoolConfig<>();
    }

    @Bean
    public SftpGenericObjectPool sftpPool(SftpFactory sftpFactory, GenericObjectPoolConfig<ChannelSftp> sftpPoolConfig){
        return new SftpGenericObjectPool(sftpFactory, sftpPoolConfig);
    }

    @Bean
    public SftpUtil sftpUtil(SftpGenericObjectPool sftpPool){
       return new SftpUtil(sftpPool);
    }

}

测试

在这里插入图片描述
项目地址:https://github.com/fengfangithub/study-sftp.git

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值