公司项目的代码用的是Hutool的FTP类进行操作,进行了大量的封装,使用起来确实简单,但它的SFTP类没找到Api手册,所以网上百度修改了工具类,使用 com.jcraft.jsch 进行开发
依赖
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.55</version>
</dependency>
配置类
@Data
@ConfigurationProperties(prefix = "media.ftp")
@Component
public class FtpConfig {
private String ip;
private Integer port;
private String username;
private String password;
private String path = "";
private String sftp_path;
private Integer sftp_port;
private String sftp_username;
private String sftp_password;
}
提示枚举类
package com.lx.xvep.media.common;
public enum FtpErrorCode {
CONNECT_SERVER_FAILER("连接sftp服务器失败"),
DISCONNECT_SERVER_GET_CONNECT_FAILER("断开sftp服务器获取连接失败"),
CREATE_DIRECTORY_FAILER("创建SFTP目录失败"),
GET_LOCAL_FILE_INPUT_STREAM("获取本地文件输入流失败"),
UPLOAD_FILE_FAILER("上传文件失败"),
GET_LOCAL_FILE_OUTPUT_STREAM("获取本地输出流失败"),
DELETE_FTP_FILE_FAILER("删除FTP文件失败"),
CD_REMOTE_PATH_FAILER("进入远程目录失败"),
LS_REMOTE_PATH_FAILER("进入远程目录失败");
private String errorDesc;
FtpErrorCode(String errorDesc) {
this.errorDesc = errorDesc;
}
public String getErrorDesc() {
return errorDesc;
}
public void setErrorDesc(String errorDesc) {
this.errorDesc = errorDesc;
}
}
SFTP操作工具类 包含常用的获取Session、关闭session、上传、下载、查询目录是否存在、创建目录等操作
package com.lx.xvep.media.utils;
import com.jcraft.jsch.*;
import com.lx.xvep.media.common.FtpErrorCode;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.Vector;
public class SFTPUtils {
private final static Logger logger = LoggerFactory.getLogger(SFTPUtils.class);
private final static int CLIENT_TIMEOUT = 3600* 1000;
ChannelSftp channelSftp = null;
private String serverIP;
private Integer port ;
private String username;
private String password;
private String encoding = "UTF-8";
public SFTPUtils(String serverIP, Integer port, String username, String password){
this.serverIP = serverIP;
if(port!=null){
this.port = port;
}
this.username = username;
this.password = password;
}
public static SFTPUtils newInstance(String serverIP, Integer port, String username, String password) {
return new SFTPUtils(serverIP,port,username,password);
}
public void connectFtp() throws Exception{
logger.info("SftpUtils start beginning");
Session session = null;
try {
JSch jSch = new JSch();
session = jSch.getSession(username,serverIP,port);
session.setTimeout(CLIENT_TIMEOUT);
if(! StringUtils.isEmpty(password)){
session.setPassword(password);
}
Properties properties = new Properties();
properties.setProperty("StrictHostKeyChecking","no");
session.setConfig(properties);
session.connect();
Channel channel = session.openChannel("sftp");
channel.connect();
channelSftp = (ChannelSftp)channel;
}catch (Exception e){
logger.info(FtpErrorCode.CONNECT_SERVER_FAILER.getErrorDesc());
throw e;
}
}
public void disConnect() throws Exception{
logger.info("SftpUtils end beginning...");
if(channelSftp != null){
Session session= null;
try {
session = channelSftp.getSession();
}catch (JSchException e){
logger.info(FtpErrorCode.DISCONNECT_SERVER_GET_CONNECT_FAILER.getErrorDesc());
throw e;
}finally {
if(session !=null){
session.disconnect();
}
}
}
}
public boolean upload(String directory, String sftpFileName, InputStream input) throws Exception {
this.connectFtp();
long start = System.currentTimeMillis();
try {
if (channelSftp.ls(directory) == null) {
channelSftp.mkdir(directory);
}
channelSftp.cd(directory);
} catch (SftpException e) {
channelSftp.mkdir(directory);
channelSftp.cd(directory);
return false;
}
try{
channelSftp.put(input, sftpFileName);
}finally {
this.disConnect();
}
logger.info("文件上传成功!! 耗时:{}ms", (System.currentTimeMillis() - start));
return true;
}
public boolean mkdirs(String createpath) throws Exception {
try {
this.connectFtp();
if (exist(createpath)) {
this.channelSftp.cd(createpath);
return true;
}
String pathArry[] = createpath.split("/");
StringBuffer filePath = new StringBuffer("/");
for (String path : pathArry) {
if (path.equals("")) {
continue;
}
filePath.append(path + "/");
if (exist(filePath.toString())) {
channelSftp.cd(filePath.toString());
} else {
channelSftp.mkdir(filePath.toString());
channelSftp.cd(filePath.toString());
}
}
this.channelSftp.cd(createpath);
} catch (SftpException e) {
logger.error("目录创建异常!", e);
return false;
}finally {
this.disConnect();
}
return true;
}
public boolean exist(String remoteDirectory) throws Exception {
boolean isDirExistFlag = false;
try {
SftpATTRS sftpATTRS = this.channelSftp.lstat(remoteDirectory);
isDirExistFlag = true;
return sftpATTRS.isDir();
} catch (Exception e) {
if (e.getMessage().toLowerCase().equals("no such file")) {
isDirExistFlag = false;
}
}
return isDirExistFlag;
}
public void ftpDownLoad(String remoteFile,String localFile) throws Exception{
logger.info("SftpUtils download beginning");
logger.info("1. 连接ftp服务器");
this.connectFtp();
logger.info("2. 创建本地文件输入流");
OutputStream outputStream = null;
try {
outputStream = new FileOutputStream(localFile);
} catch (FileNotFoundException e) {
this.disConnect();
logger.info(FtpErrorCode.GET_LOCAL_FILE_OUTPUT_STREAM.getErrorDesc());
throw new RuntimeException(e);
}
logger.info("3. 下载到本地文件/输出流");
try {
channelSftp.get(remoteFile.replaceAll("\\\\","/"),outputStream);
} catch (SftpException e) {
this.disConnect();
logger.info(FtpErrorCode.GET_LOCAL_FILE_OUTPUT_STREAM.getErrorDesc());
throw e;
}finally {
logger.info("4. 关闭sftp的连接");
this.disConnect();
}
}
public InputStream sftpWriter(String remoteFile){
InputStream is=null;
try {
logger.info("SftpUtils download beginning");
logger.info("1. 连接ftp服务器");
this.connectFtp();
logger.info("2. 创建远程文件输出流");
is = channelSftp.get(remoteFile);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (SftpException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
logger.info("3. 关闭sftp的连接");
this.disConnect();
} catch (Exception e) {
e.printStackTrace();
}
}
return is;
}
public void ftpDelete(String remoteFile) throws Exception{
logger.info("SftpUtils download beginning");
logger.info("1. 连接ftp服务器");
this.connectFtp();
logger.info("2. 删除远端文件");
String directory = remoteFile.replaceAll("\\\\","/").substring(0,remoteFile.lastIndexOf("/"));
try {
channelSftp.cd(directory);
} catch (SftpException e) {
this.disConnect();
logger.info(FtpErrorCode.DELETE_FTP_FILE_FAILER.getErrorDesc());
throw e;
}
try {
channelSftp.rm(remoteFile);
} catch (SftpException e) {
this.disConnect();
logger.info(FtpErrorCode.DELETE_FTP_FILE_FAILER.getErrorDesc());
throw e;
}finally {
logger.info("4. 关闭sftp的连接");
this.disConnect();
}
}
public List<String> findFiles(String remoteFileDirectory) throws Exception{
logger.info("find directory files beginning...");
List<String> listFile = new ArrayList<String>();
logger.info("1. 连接ftp服务器");
this.connectFtp();
logger.info("2. 效验远程目录");
logger.info("远程目录为:"+remoteFileDirectory);
try {
channelSftp.cd(remoteFileDirectory.replaceAll("\\\\","/"));
} catch (SftpException e) {
mkdirs(remoteFileDirectory.replaceAll("\\\\","/"));
return listFile;
}
logger.info("3. 查找文件名称");
Vector<?> vector = null;
try {
vector = channelSftp.ls(remoteFileDirectory.replaceAll("\\\\","/"));
for(Object obj : vector){
if(obj != null){
ChannelSftp.LsEntry entry = (ChannelSftp.LsEntry)obj;
if(!entry.getAttrs().isDir() ){
listFile.add(entry.getFilename());
}
}
}
} catch (SftpException e) {
logger.info(FtpErrorCode.LS_REMOTE_PATH_FAILER.getErrorDesc());
throw e;
}finally {
this.disConnect();
}
return listFile;
}
public List<String> findFilesLength10(String remoteFileDirectory) throws Exception{
logger.info("find directory files beginning...");
List<String> listFile = new ArrayList<String>();
logger.info("1. 连接ftp服务器");
this.connectFtp();
logger.info("2. 效验远程目录");
logger.info("远程目录为:"+remoteFileDirectory);
try {
channelSftp.cd(remoteFileDirectory.replaceAll("\\\\","/"));
} catch (SftpException e) {
mkdirs(remoteFileDirectory.replaceAll("\\\\","/"));
return listFile;
}
logger.info("3. 查找文件名称");
Vector<?> vector = null;
try {
vector = channelSftp.ls(remoteFileDirectory.replaceAll("\\\\","/"));
for(Object obj : vector){
if(obj != null){
ChannelSftp.LsEntry entry = (ChannelSftp.LsEntry)obj;
if(!entry.getAttrs().isFifo() && entry.getFilename().length() == 10){
listFile.add(entry.getFilename());
}
}
}
} catch (SftpException e) {
logger.info(FtpErrorCode.LS_REMOTE_PATH_FAILER.getErrorDesc());
throw e;
}finally {
this.disConnect();
}
return listFile;
}
public List<String> findConditionFiles(String sftpPath) throws Exception {
logger.info("find directory files beginning...");
List<String> listFile = new ArrayList<String>();
logger.info("1. 连接ftp服务器");
try {
this.connectFtp();
} catch (Exception e) {
e.printStackTrace();
}
logger.info("2. 效验远程目录");
logger.info("远程目录为:"+sftpPath);
try {
channelSftp.cd(sftpPath.replaceAll("\\\\","/"));
} catch (SftpException e) {
mkdirs(sftpPath.replaceAll("\\\\","/"));
return listFile;
}
logger.info("3. 查找文件名称");
Vector<?> vector = null;
try {
vector = channelSftp.ls(sftpPath.replaceAll("\\\\","/"));
for(Object obj : vector){
if(obj != null){
ChannelSftp.LsEntry entry = (ChannelSftp.LsEntry)obj;
if(!entry.getAttrs().isDir()){
String filename = entry.getFilename();
if ("sendnumber_202".equals(filename.trim().substring(0,14))){
listFile.add(filename);
logger.info("有效CSV同步的文件为:"+filename);
}
}
}
}
} catch (SftpException e) {
logger.info(FtpErrorCode.LS_REMOTE_PATH_FAILER.getErrorDesc());
throw e;
}finally {
this.disConnect();
}
return listFile;
}
public void moveFile(String srcFile, String destFile) throws Exception{
logger.info("1. 连接ftp服务器");
this.connectFtp();
logger.info("2. 效验目标文件的目录,如果没有则创建");
int pos = destFile.lastIndexOf("/");
this.mkdirs(destFile.substring(0,pos));
logger.info("3. 将源文件名称 重命名为 目标文件名称");
try {
channelSftp.rename(srcFile.replaceAll("\\\\","/"),destFile.replaceAll("\\\\","/"));
} catch (SftpException e) {
e.printStackTrace();
logger.info(FtpErrorCode.LS_REMOTE_PATH_FAILER.getErrorDesc());
throw e;
}finally {
this.disConnect();
}
}
}