package com.csii.loan.transfer.sftp;
import com.csii.loan.transfer.FileTransferService;
import com.jcraft.jsch.*;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.util.Arrays;
import java.util.Properties;
/**
* @author xulong
*/
public class SftpFileTransferServiceImpl implements FileTransferService {
private SftpConfig sftpConfig;
/**
* 通道类型
*/
private static final String CHANNEL_TYPE = "sftp";
private static final Logger logger = LoggerFactory.getLogger(SftpFileTransferServiceImpl.class);
/**
* 下载远程文件
*
* @param remoteFilePath 远程文件路径
* @param localDirPath 本地文件目录
* @throws JSchException
* @throws SftpException
*/
@Override
public void download(String remoteFilePath, String localDirPath) throws Exception {
File localDirFile = new File(localDirPath);
// 判断本地目录是否存在,不存在需要新建各级目录
if (!localDirFile.exists()) {
localDirFile.mkdirs();
}
ChannelSftp sftpChannel = getSftpChannel();
if (logger.isInfoEnabled()) {
logger.info("开始获取远程文件:[{}]---->[{}]", new Object[]{remoteFilePath, localDirPath});
}
sftpChannel.get(remoteFilePath, localDirPath);
if (logger.isInfoEnabled()) {
logger.info("文件下载成功");
}
disconnect(sftpChannel);
}
/**
* 获取sftp
* @author 虫子哥
* @return
* @throws JSchException
* @throws SftpException
*/
private ChannelSftp getSftpChannel() throws JSchException, SftpException {
JSch jsch = new JSch();
Session session = jsch.getSession(sftpConfig.getUsername(), sftpConfig.getHostname(), sftpConfig.getPort());
session.setPassword(sftpConfig.getPassword());
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.setTimeout(sftpConfig.getTimeout());
session.connect();
ChannelSftp sftpChannel = (ChannelSftp) session.openChannel(CHANNEL_TYPE);
sftpChannel.connect();
return sftpChannel;
}
private void disconnect(ChannelSftp sftpChannel) throws JSchException {
sftpChannel.disconnect();
sftpChannel.getSession().disconnect();
}
/**
* 文件上传
*
* @param localFilePath 本地文件路径
* @param remoteDirPath 远程目录路径
* @throws JSchException
* @throws SftpException
*/
@Override
public void upload(String localFilePath, String remoteDirPath) throws Exception {
ChannelSftp sftpChannel = getSftpChannel();
// 需要新建远程目录
mkRemoteDir(remoteDirPath, sftpChannel);
if (logger.isInfoEnabled()) {
logger.info("开始上传文件:[{}]---->[{}]", new Object[]{localFilePath, remoteDirPath});
}
sftpChannel.mkdir(remoteDirPath);
sftpChannel.put(localFilePath, remoteDirPath, ChannelSftp.OVERWRITE);
if (logger.isInfoEnabled()) {
logger.info("文件上传成功");
}
disconnect(sftpChannel);
}
/**
* 创建远程目录
*
* @param path
* @param sftp
* @throws SftpException
* @author xulong
*/
private void mkRemoteDir(String path, ChannelSftp sftp) throws SftpException {
String[] folders = path.split("/");
// 找到已经存在的目录对应的数组下标
int existDirIndex = getRemoteDirExistIndex(folders, sftp);
int dirLength = folders.length;
for (int i = existDirIndex + 1; i < dirLength; i++) {
String[] dirClone = Arrays.copyOfRange(folders, 0, i + 1);
String currentPath = StringUtils.join(dirClone, '/');
sftp.mkdir(currentPath);
}
}
/**
* 判断当前存在的目录
*
* @param folders
* @param sftp
* @return
* @author xulong
*/
private int getRemoteDirExistIndex(String[] folders, ChannelSftp sftp) {
int length = folders.length;
for (int i = 0; i < length; i++) {
// 目录从后往前开始检查是否存在
String[] cloneFolderArray = Arrays.copyOfRange(folders, 0, (length - i));
String currentPath = StringUtils.join(cloneFolderArray, '/');
try {
sftp.cd(currentPath);
// 返回当前已经存在目录的数组下标
return (length - i - 1);
} catch (SftpException e) {
System.out.println(String.format("远程目录[%s]不存在", currentPath));
continue;
}
}
return 0;
}
public void setSftpConfig(SftpConfig sftpConfig) {
this.sftpConfig = sftpConfig;
}
}
package com.csii.loan.transfer.sftp;
import org.springframework.core.io.Resource;
/**
* @author xulong
*/
public class SftpConfig {
private String hostname;
private Integer port;
private String username;
private String password;
private Integer timeout;
private Resource privateKey;
private String remoteRootPath;
private String fileSuffix;
public String getHostname() {
return hostname;
}
public void setHostname(String hostname) {
this.hostname = hostname;
}
public Integer getPort() {
return port;
}
public void setPort(Integer port) {
this.port = port;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Integer getTimeout() {
return timeout;
}
public void setTimeout(Integer timeout) {
this.timeout = timeout;
}
public Resource getPrivateKey() {
return privateKey;
}
public void setPrivateKey(Resource privateKey) {
this.privateKey = privateKey;
}
public String getRemoteRootPath() {
return remoteRootPath;
}
public void setRemoteRootPath(String remoteRootPath) {
this.remoteRootPath = remoteRootPath;
}
public String getFileSuffix() {
return fileSuffix;
}
public void setFileSuffix(String fileSuffix) {
this.fileSuffix = fileSuffix;
}
}