多线程下实现SFTP上传下载

原代码:

    private   ChannelSftp sftp;
    private   Session sshSession;
  • 上述代码导致多线程连接情况下,A线程的channel被B线程关闭
  • 上述代码将channel放置到threadlocal,共享一个sesion创建多个channel,这样会导致seesion无法关闭,始终建立连接

    private static final ThreadLocal<ChannelSftp> CHANNEL_THREAD_LOCAL = new ThreadLocal<>();
    private static final ThreadLocal<Session> SESSION_THREAD_LOCAL = new ThreadLocal<>();

    /**
     * 初始化
     *
     */
    public static void init(SftpProperties properties) {
            String host = properties.getHost();
            JSch jsch = new JSch();
        try {
            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(5000);
            if (log.isInfoEnabled()) {
                log.info("sftp connected to " + host + ".");
            }
            CHANNEL_THREAD_LOCAL.set(channel);
            SESSION_THREAD_LOCAL.set(sshSession);
            log.info("当前{}线程的sftp初始化 ,session:{},channel:{}",Thread.currentThread().getName(),sshSession,channel);
        } catch (Exception e) {
            log.error("sftp connected fail to " + host + ".");
            e.printStackTrace();
            throw new ServiceException("sftp 连接异常:"+e.toString());
        }
    }


    public static void disconnect() {
        ChannelSftp channel = CHANNEL_THREAD_LOCAL.get();
        if (channel != null && channel.isConnected()) {
            channel.disconnect();
        }
        Session session = SESSION_THREAD_LOCAL.get();
        if (session != null && session.isConnected()) {
            session.disconnect();
        }
        log.info("当前{}线程的session执行关 ,session:{},channel{}",Thread.currentThread().getName(),session,channel);
        CHANNEL_THREAD_LOCAL.remove();
        SESSION_THREAD_LOCAL.remove();
    }


    public static InputStream downloadStream(String sourcePath, String fileName) throws SftpException {
        ChannelSftp channelSftp =  CHANNEL_THREAD_LOCAL.get();
        String filePath = sourcePath + fileName;
        try {
            return channelSftp.get(filePath);
        } catch (SftpException e) {
            log.error("====Download inputStream fail :" + sourcePath + fileName, e);
            throw e;
        }
    }

  • 压测下20连接正常
    在这里插入图片描述
lcom.jcraft.jsch.ChannelSftp@2a79cdb5
2022-06-29 14:51:29.349  INFO 2664 --- [io-8090-exec-37] com.zhanghao.base.util.VcSftpUtil        : sftp connected to 10.139.60.132.
2022-06-29 14:51:29.349  INFO 2664 --- [io-8090-exec-38] com.zhanghao.base.util.VcSftpUtil        : sftp connected to 10.139.60.132.
2022-06-29 14:51:29.349  INFO 2664 --- [io-8090-exec-37] com.zhanghao.base.util.VcSftpUtil        : 当前http-nio-8090-exec-37线程的sftp初始化 ,session:com.jcraft.jsch.Session@17b545c3,channel:com.jcraft.jsch.ChannelSftp@52b7c951
2022-06-29 14:51:29.350  INFO 2664 --- [io-8090-exec-38] com.zhanghao.base.util.VcSftpUtil        : 当前http-nio-8090-exec-38线程的sftp初始化 ,session:com.jcraft.jsch.Session@4a90582,channel:com.jcraft.jsch.ChannelSftp@41ab9b73
2022-06-29 14:51:29.376  INFO 2664 --- [io-8090-exec-46] com.zhanghao.base.util.VcSftpUtil        : 当前http-nio-8090-exec-46线程的session执行关 ,session:com.jcraft.jsch.Session@54a2d9a0,channelcom.jcraft.jsch.ChannelSftp@5a653d44
2022-06-29 14:51:29.407  INFO 2664 --- [io-8090-exec-39] com.zhanghao.base.util.VcSftpUtil        : sftp connected to 10.139.60.132.
2022-06-29 14:51:29.407  INFO 2664 --- [io-8090-exec-39] com.zhanghao.base.util.VcSftpUtil        : 当前http-nio-8090-exec-39线程的sftp初始化 ,session:com.jcraft.jsch.Session@747a7f84,channel:com.jcraft.jsch.ChannelSftp@3178ef6f
2022-06-29 14:51:29.461  INFO 2664 --- [io-8090-exec-38] com.zhanghao.base.util.VcSftpUtil        : 当前http-nio-8090-exec-38线程的session执行关 ,session:com.jcraft.jsch.Session@4a90582,channelcom.jcraft.jsch.ChannelSftp@41ab9b73
2022-06-29 14:51:29.461  INFO 2664 --- [io-8090-exec-37] com.zhanghao.base.util.VcSftpUtil        : 当前http-nio-8090-exec-37线程的session执行关 ,session:com.jcraft.jsch.Session@17b545c3,channelcom.jcraft.jsch.ChannelSftp@52b7c951
2022-06-29 14:51:29.471  INFO 2664 --- [io-8090-exec-40] com.zhanghao.base.util.VcSftpUtil        : sftp connected to 10.139.60.132.
2022-06-29 14:51:29.471  INFO 2664 --- [io-8090-exec-40] com.zhanghao.base.util.VcSftpUtil        : 当前http-nio-8090-exec-40线程的sftp初始化 ,session:com.jcraft.jsch.Session@6673547a,channel:com.jcraft.jsch.ChannelSftp@2371d6d0
2022-06-29 14:51:29.485  INFO 2664 --- [io-8090-exec-41] com.zhanghao.base.util.VcSftpUtil        : sftp connected to 10.139.60.132.
2022-06-29 14:51:29.485  INFO 2664 --- [io-8090-exec-41] com.zhanghao.base.util.VcSftpUtil        : 当前http-nio-8090-exec-41线程的sftp初始化 ,session:com.jcraft.jsch.Session@7cbb05a0,channel:com.jcraft.jsch.ChannelSftp@39b98453
2022-06-29 14:51:29.520  INFO 2664 --- [io-8090-exec-39] com.zhanghao.base.util.VcSftpUtil        : 当前http-nio-8090-exec-39线程的session执行关 ,session:com.jcraft.jsch.Session@747a7f84,channelcom.jcraft.jsch.ChannelSftp@3178ef6f
2022-06-29 14:51:29.553  INFO 2664 --- [io-8090-exec-42] com.zhanghao.base.util.VcSftpUtil        : sftp connected to 10.139.60.132.
2022-06-29 14:51:29.553  INFO 2664 --- [io-8090-exec-47] com.zhanghao.base.util.VcSftpUtil        : sftp connected to 10.139.60.132.
2022-06-29 14:51:29.553  INFO 2664 --- [io-8090-exec-42] com.zhanghao.base.util.VcSftpUtil        : 当前http-nio-8090-exec-42线程的sftp初始化 ,session:com.jcraft.jsch.Session@e05db62,channel:com.jcraft.jsch.ChannelSftp@4b0744c6
2022-06-29 14:51:29.553  INFO 2664 --- [io-8090-exec-47] com.zhanghao.base.util.VcSftpUtil        : 当前http-nio-8090-exec-47线程的sftp初始化 ,session:com.jcraft.jsch.Session@1d4f4216,channel:com.jcraft.jsch.ChannelSftp@1388bfcf
2022-06-29 14:51:29.584  INFO 2664 --- [io-8090-exec-40] com.zhanghao.base.util.VcSftpUtil        : 当前http-nio-8090-exec-40线程的session执行关 ,session:com.jcraft.jsch.Session@6673547a,channelcom.jcraft.jsch.ChannelSftp@2371d6d0
2022-06-29 14:51:29.607  INFO 2664 --- [io-8090-exec-41] com.zhanghao.base.util.VcSftpUtil        : 当前http-nio-8090-exec-41线程的session执行关 ,session:com.jcraft.jsch.Session@7cbb05a0,channelcom.jcraft.jsch.ChannelSftp@39b98453
2022-06-29 14:51:29.657  INFO 2664 --- [io-8090-exec-48] com.zhanghao.base.util.VcSftpUtil        : sftp connected to 10.139.60.132.
2022-06-29 14:51:29.658  INFO 2664 --- [io-8090-exec-48] com.zhanghao.base.util.VcSftpUtil        : 当前http-nio-8090-exec-48线程的sftp初始化 ,session:com.jcraft.jsch.Session@3d660d1,channel:com.jcraft.jsch.ChannelSftp@30305491
2022-06-29 14:51:29.725  INFO 2664 --- [io-8090-exec-47] com.zhanghao.base.util.VcSftpUtil        : 当前http-nio-8090-exec-47线程的session执行关 ,session:com.jcraft.jsch.Session@1d4f4216,channelcom.jcraft.jsch.ChannelSftp@1388bfcf
2022-06-29 14:51:29.725  INFO 2664 --- [io-8090-exec-42] com.zhanghao.base.util.VcSftpUtil        : 当前http-nio-8090-exec-42线程的session执行关 ,session:com.jcraft.jsch.Session@e05db62,channelcom.jcraft.jsch.ChannelSftp@4b0744c6
2022-06-29 14:51:29.730  INFO 2664 --- [io-8090-exec-43] com.zhanghao.base.util.VcSftpUtil        : sftp connected to 10.139.60.132.
2022-06-29 14:51:29.730  INFO 2664 --- [io-8090-exec-43] com.zhanghao.base.util.VcSftpUtil        : 当前http-nio-8090-exec-43线程的sftp初始化 ,session:com.jcraft.jsch.Session@6c9c5e42,channel:com.jcraft.jsch.ChannelSftp@299ecdb5
2022-06-29 14:51:29.826  INFO 2664 --- [io-8090-exec-48] com.zhanghao.base.util.VcSftpUtil        : 当前http-nio-8090-exec-48线程的session执行关 ,session:com.jcraft.jsch.Session@3d660d1,channelcom.jcraft.jsch.ChannelSftp@30305491
2022-06-29 14:51:29.889  INFO 2664 --- [io-8090-exec-43] com.zhanghao.base.util.VcSftpUtil        : 当前http-nio-8090-exec-43线程的session执行关 ,session:com.jcraft.jsch.Session@6c9c5e42,channelcom.jcraft.jsch.ChannelSftp@299ecdb5

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用JSch库来实现在Java中上文件到SFTP服务器的功能,以下是一个简单的示例代码: ```java import com.jcraft.jsch.Channel; import com.jcraft.jsch.ChannelSftp; import com.jcraft.jsch.JSch; import com.jcraft.jsch.Session; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; public class SftpUploader { private String host; private int port; private String username; private String password; private String remoteDirectory; public SftpUploader(String host, int port, String username, String password, String remoteDirectory) { this.host = host; this.port = port; this.username = username; this.password = password; this.remoteDirectory = remoteDirectory; } public void uploadFile(String localFilePath, String remoteFilename) throws Exception { JSch jsch = new JSch(); Session session = jsch.getSession(username, host, port); session.setPassword(password); session.setConfig("StrictHostKeyChecking", "no"); session.connect(); Channel channel = session.openChannel("sftp"); channel.connect(); ChannelSftp sftpChannel = (ChannelSftp) channel; sftpChannel.cd(remoteDirectory); File localFile = new File(localFilePath); InputStream inputStream = new FileInputStream(localFile); sftpChannel.put(inputStream, remoteFilename); inputStream.close(); sftpChannel.exit(); session.disconnect(); } } ``` 在上面的代码中,`SftpUploader`类的构造函数接收SFTP服务器的主机名、端口号、用户名、密码和远程目录路径。`uploadFile`方法接收本地文件路径和远程文件名,然后将文件上到远程SFTP服务器。可以在多个线程中创建`SftpUploader`实例并调用`uploadFile`方法来同时上多个文件。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值