111 lines
3.3 KiB
Java
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();
|
|
}
|
|
}
|
|
}
|