windows 上搭建 sftp 服务器 --freesshd
1. 配置类
package com.test.sftp;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct;
/**
* Created by luxian.zhang on 2021/5/10.
*/
@Configuration
public class SftpConfig {
public final static String SEPERATOR = "/";
@Value("${sftp.host:}")
private String host;//sftp服务器ip
@Value("${sftp.username:}")
private String username;//用户名
@Value("${sftp.password:}")
private String password;//密码
@Value("${sftp.private.key:}")
private String privateKey;//密钥文件路径
@Value("${sftp.passphrase:}")
private String passphrase;//密钥口令
@Value("${sftp.port:}")
private Integer port;//默认的sftp端口号是22
@Value("${sftp.program.dir:}")
private String programDir;//程式根目录, 默认/
public static String HOST;
public static String USERNAME;
public static String PASSWORD;
public static String PRIVATE_KEY;
public static String PASSPHRASE;
public static Integer PORT;
public static String PROGRAM_DIR;
@PostConstruct
public void init() {
HOST = host;
USERNAME = username;
PASSWORD = password;
PRIVATE_KEY = privateKey;
PASSPHRASE = passphrase;
if(port == null){
port = 22;
}
PORT = port;
PROGRAM_DIR = programDir;
}
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
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 String getPrivateKey() {
return privateKey;
}
public void setPrivateKey(String privateKey) {
this.privateKey = privateKey;
}
public String getPassphrase() {
return passphrase;
}
public void setPassphrase(String passphrase) {
this.passphrase = passphrase;
}
public Integer getPort() {
return port;
}
public void setPort(Integer port) {
this.port = port;
}
public String getProgramDir() {
return programDir;
}
public void setProgramDir(String programDir) {
this.programDir = programDir;
}
}
2. 操作类和调试
package com.test.sftp;
import com.alibaba.fastjson.JSON;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpATTRS;
import com.test.utils.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;
import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.Vector;
/**
* Created by luxian.zhang on 2021/5/10.
*/
public class SftpConn {
private static Logger _log = LoggerFactory.getLogger(SftpConn.class);
private ChannelSftp sftp = null;
private Session session = null;
private String rootDir;
public SftpConn() throws Exception{
if(StringUtil.isNullOrEmpty(SftpConfig.HOST)){
throw new RuntimeException("sftp配置不全 【 sftp.host, sftp.username, sftp.password 】");
}
getSftpChannel(SftpConfig.HOST, SftpConfig.USERNAME, SftpConfig.PASSWORD, SftpConfig.PRIVATE_KEY, SftpConfig.PASSPHRASE, SftpConfig.PORT, SftpConfig.PROGRAM_DIR);
}
public SftpConn(String host, String username, String password, String privateKey, String passphrase, Integer port, String rootDir) throws Exception{
getSftpChannel(host, username, password, privateKey, passphrase, port, rootDir);
}
private void getSftpChannel(String host, String username, String password, String privateKey, String passphrase, Integer port, String rootDir) throws Exception{
if(port == null){
port = 22;
}
if(StringUtil.isNullOrEmpty(host)){
return;
}
try {
JSch jsch = new JSch();
if (privateKey != null && !"".equals(privateKey)) {
//使用密钥验证方式,密钥可以使有口令的密钥,也可以是没有口令的密钥
if (passphrase != null && "".equals(passphrase)) {
jsch.addIdentity(privateKey, passphrase);
} else {
jsch.addIdentity(privateKey);
}
}
session = jsch.getSession(username, host, port);
if (password != null && !"".equals(password)) {
session.setPassword(password);
}
Properties sshConfig = new Properties();
sshConfig.put("StrictHostKeyChecking", "no");// do not verify host key
session.setConfig(sshConfig);
// session.setTimeout(timeout);
session.setServerAliveCountMax(40);
session.setServerAliveInterval(92000);
session.connect();
//参数sftp指明要打开的连接是sftp连接
sftp = (ChannelSftp)session.openChannel("sftp");
sftp.connect();
if(rootDir == null){
rootDir = "";
}
this.rootDir = rootDir;
} catch (Exception e) {
SftpConn.disconnect(this);
throw e;
}
}
/**
* 上传文件并且清理目录
* @param directory
* @param uploadFileList
* @throws Exception
*/
public void cleanAndUplaod(String directory, List<String> uploadFileList) throws Exception{
if(StringUtil.isNullOrEmpty(directory)){
throw new RuntimeException("参数错误,上传的目标目录为空");
}
this.upload(directory, uploadFileList, true);
}
/**
* 上传文件并且清理目录
* @param srcDir
* @param directory 相对sftp根目录
* @throws Exception
*/
public void cleanAndUplaod(String srcDir, String directory) throws Exception{
if(StringUtil.isNullOrEmpty(srcDir) || StringUtil.isNullOrEmpty(directory)){
return;
}
File srcDirFile = new File(srcDir);
List<String> uploadFileList = new ArrayList<>();
if(!srcDirFile.exists()){
return;
}
File[] files = srcDirFile.listFiles();
for (File file : files) {
uploadFileList.add(file.getAbsolutePath());
}
this.upload(directory, uploadFileList, true);
}
/**
* 创建目录
* @param createpath
* @return
*/
public boolean createDir(String createpath) throws Exception{
if (isDirExist(createpath)){
return true;
}
String pathArry[] = createpath.split(SftpConfig.SEPERATOR);
StringBuffer filePath = new StringBuffer(SftpConfig.SEPERATOR);
for (String path : pathArry){
if (path.equals("")){
continue;
}
filePath.append(path + SftpConfig.SEPERATOR);
if (isDirExist(filePath.toString())){
sftp.cd(filePath.toString());
} else{
// 建立目录
sftp.mkdir(filePath.toString());
}
}
return true;
}
/**
* 上传文件
* @param directory 目标目录绝对路径
* @param uploadFileList 上传的文件路径
* @param clearDir 是否需要清理目录
* @throws Exception
*/
public void upload(String directory, List<String> uploadFileList, boolean clearDir) throws Exception {
if(CollectionUtils.isEmpty(uploadFileList)){
return;
}
if(StringUtil.isNullOrEmpty(directory)){
directory = SftpConfig.SEPERATOR;
}
_log.info("===== SFTP 上传文件开始 {} to {} ", JSON.toJSONString(uploadFileList), directory);
long start = System.currentTimeMillis();
//不是根目录
if(!directory.equals(SftpConfig.SEPERATOR)){
//创建目录
boolean exist = isDirExist(directory);
if(!exist){
//不存在就创建
createDir(directory);
}
if(exist && clearDir){
//如果存在那么需要清空目录里面的文件
Vector<ChannelSftp.LsEntry> vector = sftp.ls(directory);
int size = vector.size();
for (int i = 0; i < size; i++) {
ChannelSftp.LsEntry file = vector.get(i);
String fileName = file.getFilename();
this.deleteFile(directory, fileName);
}
}
}
sftp.cd(directory);
for (String filePath : uploadFileList) {
File file = new File(filePath);
sftp.put(new FileInputStream(file), file.getName());
}
_log.info("===== SFTP 上传文件成功 to {} spends {} ms", directory, System.currentTimeMillis() - start);
}
/**
* 判断目录是否存在
* @param directory
* @return
*/
public boolean isDirExist(String directory){
boolean isDirExistFlag = false;
try {
SftpATTRS sftpATTRS = sftp.lstat(directory);
isDirExistFlag = true;
return sftpATTRS.isDir();
} catch (Exception e){
if (e.getMessage().toLowerCase().equals("no such file")){
isDirExistFlag = false;
}
}
return isDirExistFlag;
}
/**
* 删除stfp文件
* @param directory:要删除文件所在目录
* @param deleteFile:要删除的文件
*/
public void deleteFile(String directory, String deleteFile) throws Exception{
if(deleteFile.equals(".") || deleteFile.equals("..")){
return;
}
sftp.rm(directory + SftpConfig.SEPERATOR + deleteFile);
}
/**
* 关闭连接
*/
public static void disconnect(SftpConn sftpConn){
if(sftpConn == null){
return;
}
ChannelSftp sftp = sftpConn.getSftp();
Session session = sftpConn.getSession();
if (sftp != null && sftp.isConnected()){
sftp.disconnect();
}
if (session != null && session.isConnected()){
session.disconnect();
}
}
public ChannelSftp getSftp() {
return sftp;
}
public void setSftp(ChannelSftp sftp) {
this.sftp = sftp;
}
public Session getSession() {
return session;
}
public void setSession(Session session) {
this.session = session;
}
public static void main(String[] args) {
String host = "192.168.1.103";
String username = "test";
String password = "110110";
List<String> uploadFileList = new ArrayList<>();
uploadFileList.add("D:\\machine\\CNC01\\3F01.NC");
uploadFileList.add("D:\\machine\\CNC01\\4F02.J00");
SftpConn sftp = null;
try {
String rootDir = SftpConfig.SEPERATOR + "machine";
sftp = new SftpConn(host, username, password, null, null, null, rootDir);
sftp.cleanAndUplaod(rootDir + SftpConfig.SEPERATOR + "CNC02", uploadFileList);
} catch (Exception e) {
_log.error("上传文件出错", e);
} finally {
SftpConn.disconnect(sftp);
}
}
}