Files
data-migration/filesync/src/main/java/com/njcn/filesync/sftp/SftpClient.java
2025-11-03 16:30:58 +08:00

111 lines
3.3 KiB
Java

package com.njcn.filesync.sftp;
import com.jcraft.jsch.*;
import com.njcn.filesync.config.ServerConfig;
import lombok.Data;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import java.io.File;
import java.util.Vector;
/**
* Description:
* Date: 2025/10/16 下午 3:00【需求编号】
*SFTP客户端实现
* @author clam
* @version V1.0.0
*/
@Service
@Data
public class SftpClient implements AutoCloseable{
private static final Logger logger = LoggerFactory.getLogger(SftpClient.class);
private JSch jsch;
private Session session;
private ChannelSftp channel;
public void connect(ServerConfig config) throws JSchException {
jsch = new JSch();
// 设置私钥(如果提供)
if (config.getPrivateKeyPath() != null && !config.getPrivateKeyPath().isEmpty()) {
jsch.addIdentity(config.getPrivateKeyPath());
}
session = jsch.getSession(config.getUsername(), config.getHost(), config.getPort());
// 设置密码(如果提供)
if (config.getPassword() != null && !config.getPassword().isEmpty()) {
session.setPassword(config.getPassword());
}
// 配置SSH连接
java.util.Properties sshConfig = new java.util.Properties();
sshConfig.put("StrictHostKeyChecking", "no");
session.setConfig(sshConfig);
session.connect(30000); // 30秒超时
// 打开SFTP通道
channel = (ChannelSftp) session.openChannel("sftp");
channel.connect(30000);
}
public void uploadFile(String localFile, String remotePath) throws SftpException {
File file = new File(localFile);
String remoteFile = ensureRemotePath(remotePath, file.getName());
// 确保远程目录存在
createRemoteDirectory(remotePath);
// 上传文件
channel.put(localFile, remoteFile);
}
public ChannelSftp.LsEntry getRemoteFileInfo(String remotePath) throws SftpException {
@SuppressWarnings("unchecked")
Vector<ChannelSftp.LsEntry> files = channel.ls(remotePath);
if (files != null && !files.isEmpty()) {
return files.get(0);
}
return null;
}
private String ensureRemotePath(String remotePath, String fileName) {
if (remotePath.endsWith("/")) {
return remotePath + fileName;
} else {
return remotePath + "/" + fileName;
}
}
void createRemoteDirectory(String remotePath) throws SftpException {
// 处理Windows路径分隔符
String normalizedPath = remotePath.replace("\\", "/");
String[] directories = normalizedPath.split("/");
StringBuilder currentPath = new StringBuilder();
try {
channel.mkdir(normalizedPath);
logger.debug("Created remote directory: {}", currentPath);
} catch (SftpException e) {
if (e.id != ChannelSftp.SSH_FX_FAILURE) {
// 目录可能已存在,忽略这个错误
logger.debug("Directory may already exist: {}", currentPath);
}
}
}
@Override
public void close() {
if (channel != null) {
channel.disconnect();
}
if (session != null) {
session.disconnect();
}
}
}