- 前言
- 一、jsch存在的问题
- 二、Apache米娜的使用
- 1.引入库
- 2.上传与下载
- 总结
前言
距离上一次写博客已经过去很久了,可能是项目太忙了,正好本周末抽个空写一写,不然后面可能自己都忘记了。
我相信众多开发者现在用java连接sftp,依然是引入的jsch依赖包,然而jsch在官网的最后一次更新也已经是2018年了。所以今天的博客就来讲解了一些jsch的问题,以及如何使用Apache的米娜mina来代替jsch,米娜是Apache的产品,目前一直在更新。英文水平好的同学可以参考官网:Welcome to Apache MINA
一、jsch存在的问题
jsch存在的问题,我贴了几个链接,其中也包括部分解决方案,但是我觉得这可能只是权宜之计。
1、jsch报错4: Failure
2、SFTP编程开源框架jsch 异常问题汇总
3、实际在多线程使用中的问题以及其他奇奇怪怪的问题(这个需要根据实际情况来看,所以就没有相关链接了)
二、Apache米娜的使用 1.引入库依赖包如下(不同版本可能API会有些区别,本博客不演示其他版本,如有小伙伴有疑问,可在评论区留言):
2.上传与下载org.apache.sshd sshd-core 2.7.0 org.apache.sshd sshd-sftp 2.7.0 net.i2p.crypto eddsa 0.3.0
代码如下(示例中演示了登录,退出登录,判断目录或文件是否存在,列举目录文件,创建目录,上传文件,下载文件等常用操作,如有其他疑问,请在评论区留言):
import org.apache.sshd.client.SshClient;
import org.apache.sshd.client.session.ClientSession;
import org.apache.sshd.sftp.client.SftpClientFactory;
import org.apache.sshd.sftp.client.fs.SftpFileSystem;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.stream.Collectors;
public class MinaTest {
public static void main(String[] args) {
// sftp信息
String sftpAddr = "127.0.0.1";
Integer sftpPort = 22;
String sftpUser = "test";
String sftpPassword = "test";
try {
// 定义sftp连接的客户端
SshClient client = SshClient.setUpDefaultClient();
// 开启客户端
client.start();
// 创建session会话
ClientSession session = client.connect(sftpUser, sftpAddr, sftpPort).verify().getSession();
// 设置密码
session.addPasswordIdentity(sftpPassword);
// 校验密码,检验密码是需要设置超时时间
Integer timeOut = 5000;
if (session.auth().verify(timeOut).isFailure()) {
System.out.println("sftp密码校验失败,请检查!");
} else {
// 密码校验成功后,创建sftp文件系统,此时sftp已经连接成功
SftpFileSystem fs = SftpClientFactory.instance().createSftpFileSystem(session);
System.out.println("sftp连接成功,sftpAddr -->" + sftpAddr + ",sftpPort -->" + sftpPort + ",sftpUser -->" + sftpUser + ",sftpPassword -->" + sftpPassword);
// 判断目录或文件是否存在
// 远程路径,可以是相对路径,也可绝对路径
String sftpFilePath = "test/helloword.txt";
boolean exists = Files.exists(fs.getDefaultDir().resolve(sftpFilePath));
System.out.println("exists -->" + exists);
// 列举目录下文件
// 远程路径,可以是相对路径,也可绝对路径
sftpFilePath = "test/";
Path remoteFile = fs.getDefaultDir().resolve(sftpFilePath);
List list = Files.list(remoteFile).collect(Collectors.toList());
System.out.println("文件列表 --->" + list.toString());
// 创建文件夹
// 远程路径,可以是相对路径,也可绝对路径
sftpFilePath = "test/20220601/";
Path remoteRoot = fs.getDefaultDir().resolve(sftpFilePath);
if (!Files.exists(remoteRoot)) {
Files.createDirectories(remoteRoot);
System.out.println("目录创建成功 -->" + sftpFilePath);
}
// 上传文件
// 远程路径,可以是相对路径,也可绝对路径
sftpFilePath = "test/20220601/";
// 需要追加文件名
String localFilePath = "D:\helloword.txt";
// 上传后的文件名可以自定义
String sftpFileName = "helloword.txt";
Path remoteRoot1 = fs.getDefaultDir().resolve(sftpFilePath);
if (!Files.exists(remoteRoot1)) {
Files.createDirectories(remoteRoot1);
}
Path remoteFile1 = remoteRoot.resolve(sftpFileName);
// 删除文件
Files.deleteIfExists(remoteFile1);
Files.copy(Paths.get(localFilePath), remoteFile1);
System.out.println("sftp文件上传成功,文件名为 -->" + sftpFilePath.concat(sftpFileName));
// 下载文件
// 远程路径
sftpFilePath = "test/20220601/";
// 远程文件名
sftpFileName = "helloword.txt";
// 本地文件路径,需带上文件名,文件名可自定义
localFilePath = "D:\helloword2.txt";
// 如果存在则删除已下载文件
Files.deleteIfExists(Paths.get(localFilePath));
// 创建本地文件夹
Path localPath = Paths.get(localFilePath.substring(0, localFilePath.lastIndexOf(File.separator)));
Files.createDirectories(localPath);
// 远程文件path
Path remoteFile2 = fs.getDefaultDir().resolve(sftpFilePath).resolve(sftpFileName);
Files.copy(remoteFile2, Paths.get(localFilePath));
System.out.println("sftp文件下载成功,文件名为 -->" + localFilePath);
// 关闭连接,顺序很重要,后创建的先关
if (null != fs) {
fs.close();
}
if (null != session) {
session.close();
}
if (null != client) {
client.stop();
}
}
} catch (IOException e) {
// 异常自行捕捉处理
e.printStackTrace();
}
}
}
总结
基于上述直观的代码演示,可以看出,米娜的sftp实现比较简单,基本上是登录后把sftp当初一个文件系统,然后上传和下载的操作都可看成是对文件的copy,这样理解起来可能更容易一些。
本人才疏学浅,对于Apache米娜的运用仅限于此,国内也少有相关教程,还望江湖的各位大佬多多指点。



