我们在开发中,有时候需要操作服务器上的文件,Spring Boot可以使用JSch库来连接SFTP并进行操作服务器上的文件读写。
创建一个SFTP连接需要以下步骤:
- 1.创建JSch对象
- 2.使用JSch对象创建Session对象
- 3.使用Session对象连接到SFTP服务器
- 4.打开SFTP通道
- 5.使用SFTP通道打开SFTP连接
1.添加依赖
在pom.xml
文件中添加以下依赖:
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.55</version>
</dependency>
2.创建SftpConfig
配置类
import lombok.Getter;
import lombok.Setter;
/**
* <p>
* SFTP连接参数配置类
* description: 如果后续只需要操作一台固定不变的服务器,可以从配置文件中读取
* </p>
*
* @author snogzixian
* @Url 宋子宪博客 www.songzixian.com
* @since 2023-03-13
*/
@Setter
@Getter
public class SftpConfig {
/**
* SFTP服务器地址
*/
private String host;
/**
* SFTP服务器端口
*/
private int port;
/**
* SFTP服务器用户名
*/
private String username;
/**
* SFTP服务器密码 如果不使用密码方式则留空
*/
private String password;
/**
* 密钥文件路径,如果不使用密钥连接则留空
*/
private String privateKeyPath;
/**
* 密钥文件口令,如果不使用密钥连接则留空
*/
private String passphrase;
/**
* 连接SFTP服务器超时时间 2秒
*/
private Integer sessionConnectTimeoutTime = 2000;
/**
* 打开通道超时时间 2秒
*/
private Integer channelSftpConnectTimeoutTime = 2000;
/**
* 密码方式连接方法
*
* @param host SFTP服务器地址
* @param port SFTP服务器端口
* @param username SFTP服务器用户名
* @param password SFTP服务器密码 如果不使用连接则留空
*/
public SftpConfig(String host, int port, String username, String password) {
this.host = host;
this.port = port;
this.username = username;
this.password = password;
}
/**
* 秘钥方式连接方法
*
* @param host SFTP服务器地址
* @param port SFTP服务器端口
* @param username SFTP服务器用户名
* @param privateKeyPath 密钥文件路径,如果不使用密钥连接则留空
* @param passphrase 密钥文件口令,如果不使用密钥连接则留空
*/
public SftpConfig(String host, int port, String username,String privateKeyPath, String passphrase) {
this.host = host;
this.port = port;
this.username = username;
this.privateKeyPath = privateKeyPath;
this.passphrase = passphrase;
}
}
3.创建SFTP操作工具类
import com.jcraft.jsch.*;
import com.risk.riskControl.config.SftpConfig;
import java.io.*;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* <p>
* SFTP操作工具类
* </p>
*
* @author snogzixian
* @Url 宋子宪博客 www.songzixian.com
* @since 2023-03-13
*/
public class SftpService {
/**
* SFTP连接参数
*/
private SftpConfig config;
/**
* JSch对象,用于创建SFTP连接
*/
private JSch jsch;
/**
* Session对象,用于连接到SFTP服务器
*/
private Session session;
/**
* SFTP通道,用于打开SFTP连接
*/
private ChannelSftp channelSftp;
/**
* 构造函数,初始化SFTP连接参数
*
* @param config SFTP连接参数
*/
public SftpService(SftpConfig config) {
this.config = config;
// 创建JSch对象
this.jsch = new JSch();
}
/**
* 连接到SFTP服务器
*
* @throws JSchException
*/
public void connect() throws JSchException {
try {
// 创建Session对象
session = jsch.getSession(config.getUsername(), config.getHost(), config.getPort());
if (config.getPassword() != null) {
// 使用密码连接
session.setPassword(config.getPassword());
} else if (config.getPrivateKeyPath() != null) {
// 使用私钥连接
jsch.addIdentity(config.getPrivateKeyPath(), config.getPassphrase());
}
// 不进行主机密钥检查
session.setConfig("StrictHostKeyChecking", "no");
// 设置SFTP连接超时时间
session.connect(config.getSessionConnectTimeoutTime());
// 打开SFTP通道
channelSftp = (ChannelSftp) session.openChannel("sftp");
// 设置通道连接超时时间
channelSftp.connect(config.getChannelSftpConnectTimeoutTime());
} catch (JSchException e) {
// 连接异常处理
throw new JSchException("Failed to connect to SFTP server: " + e.getMessage());
}
}
/**
* 断开SFTP连接
*/
public void disconnect() {
if (channelSftp != null) {
// 断开SFTP连接
channelSftp.disconnect();
}
if (session != null) {
// 断开Session连接
session.disconnect();
}
}
/**
* 上传文件到SFTP服务器
*
* @param localFilePath 本地文件路径
* @param remoteFilePath SFTP服务器文件路径
* @throws SftpException
* @throws FileNotFoundException
*/
public void uploadFile(String localFilePath, String remoteFilePath) throws SftpException, IOException {
// 使用try-with-resources语句,可以自动关闭资源
try (InputStream inputStream = new FileInputStream(localFilePath)) {
// 上传文件到SFTP服务器
channelSftp.put(inputStream, remoteFilePath);
}
}
/**
* 从SFTP服务器下载文件
*
* @param remoteFilePath SFTP服务器文件路径
* @param localFilePath 本地文件路径
* @throws SftpException
* @throws FileNotFoundException
*/
public void downloadFile(String remoteFilePath, String localFilePath) throws SftpException, IOException {
// 使用try-with-resources语句,可以自动关闭资源
try (OutputStream outputStream = new FileOutputStream(localFilePath)) {
// 从SFTP服务器下载文件
channelSftp.get(remoteFilePath, outputStream);
}
}
/**
* 删除SFTP服务器上的文件
*
* @param remoteFilePath SFTP服务器文件路径
* @throws SftpException
*/
public void deleteFile(String remoteFilePath) throws SftpException {
// 删除SFTP服务器上的文件
channelSftp.rm(remoteFilePath);
}
/**
* 列出SFTP服务器上的文件
* 使用这段代码会有什么问题,是否还可以优化
*
* @param remoteDirectory SFTP服务器目录
* @return 文件列表
* @throws SftpException
*/
public List<String> listFiles(String remoteDirectory) throws SftpException {
List<String> fileList;
// 列出SFTP服务器上的文件
try (Stream<ChannelSftp.LsEntry> stream = channelSftp.ls(remoteDirectory).stream()) {
fileList = stream
// 过滤掉目录
.filter(entry -> !entry.getAttrs().isDir())
// 获取文件名
.map(ChannelSftp.LsEntry::getFilename)
// 将文件名收集到List中
.collect(Collectors.toList());
}
return fileList;
}
}
4.创建SftpTest测试类
import com.risk.riskControl.config.SftpConfig;
import java.util.List;
/**
* /**
* <p>
* SftpTest测试类
* </p>
*
* @author snogzixian
* @Url 宋子宪博客 www.songzixian.com
* @since 2023-03-13
*/
public class SftpTest {
/**
* 测试SFTP连接及文件上传、下载、删除、列出操作
*
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
// 构建SFTP参数,如果是参数固定一个不变改为用配置文件读取
SftpConfig config = new SftpConfig("sftp.songzixian.com", 22, "szxBlog", "12345678");
// 秘钥方式连接
//SftpConfig config = new SftpConfig("sftp.songzixian.com", 22, "root", "D:\\id_rsa_szx_blog.ppk","blog123");
// 连接到SFTP服务器
SftpService sftpService = new SftpService(config);
sftpService.connect();
// 本地路径
String localFilePath = "";
// 服务器路径
String remoteFilePath = "";
// 上传文件使用
// 本地文件路径
localFilePath = "D:\\code\\a.txt";
// SFTP服务器文件路径
remoteFilePath = "/usr/local/sftp-test/a.txt";
// 上传文件到SFTP服务器
sftpService.uploadFile(localFilePath, remoteFilePath);
// 下载文件使用
// SFTP服务器文件路径
remoteFilePath = "/usr/local/sftp-test/a.txt";
// 本地文件路径
localFilePath = "D:\\code\\aaaa.txt";
// 从SFTP服务器下载文件
sftpService.downloadFile(remoteFilePath, localFilePath);
// 删除文件使用
remoteFilePath = "/usr/local/sftp-test/a.txt";
// 删除SFTP服务器上的文件
sftpService.deleteFile(remoteFilePath);
// 列出文件
// SFTP服务器目录
String remoteDirectory = "/usr/local/sftp-test/";
// 列出SFTP服务器上的文件
List<String> files = sftpService.listFiles(remoteDirectory);
for (String file : files) {
System.out.println(file);
}
System.out.println("操作成功");
// 断开SFTP连接
sftpService.disconnect();
}
}