<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
<version>3.6</version>
</dependency>
@Slf4j
public class FTPUtils {
/**
* 连接,如果失败重试3次,间隔1s
*
* @param server
* @return
*/
public static FTPClient connectFtp(FTPServer server) {
FTPClient ftpClient = new FTPClient();
ftpClient.setControlEncoding(server.getEncoding());
for (int i = 0; i < 3; i++) {
try {
log.info("connecting...ftp服务器:" + server.getIp() + ":" + server.getPort());
ftpClient.connect(server.getIp(), server.getPort()); //连接ftp服务器
ftpClient.login(server.getAccount(), server.getPwd()); //登录ftp服务器
int replyCode = ftpClient.getReplyCode(); //是否成功登录服务器
if (FTPReply.isPositiveCompletion(replyCode)) {
log.info("连接成功...ftp服务器" + server.getIp() + ":" + server.getPort());
break;
}
Thread.sleep(1000);
log.info("连接失败...ftp服务器" + server.getIp() + ":" + server.getPort());
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
return ftpClient;
}
/**
* 下载文件 *
*
* @param pathname FTP服务器文件目录 *
* @param filename 文件名称 *
* @param localpath 下载后的文件路径 *
* @return
*/
public static boolean downloadFile(FTPClient ftpClient, String pathname, String filename, String localpath) {
OutputStream os = null;
try {
log.info("开始下载文件");
ftpClient.enterLocalPassiveMode();
//切换FTP目录
ftpClient.changeWorkingDirectory(pathname);
FTPFile[] ftpFiles = ftpClient.listFiles();
for (FTPFile file : ftpFiles) {
if (filename.equalsIgnoreCase(file.getName())) {
File localFile = new File(localpath + file.getName());
os = new FileOutputStream(localFile);
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
boolean flag = ftpClient.retrieveFile(file.getName(), os);
if (!flag) {
log.info("下载文件失败:" + file.getName());
return false;
} else {
log.info("下载文件成功" + file.getName());
}
}
}
} catch (Exception e) {
log.info("下载文件失败" + e.getMessage(), e);
return false;
} finally {
if (os != null) {
try {
os.close();
} catch (IOException e) {
}
}
}
return true;
}
/**
* 删除文件 *
*
* @param filename 要删除的文件名称 *
* @return
*/
public static boolean deleteFile(FTPClient ftpClient, String filename, String pathname) {
try {
ftpClient.enterLocalPassiveMode();
ftpClient.changeWorkingDirectory(pathname);
log.info("开始删除文件");
boolean flag = ftpClient.deleteFile(pathname + filename);
log.info("删除文件成功");
return flag;
} catch (Exception e) {
log.error("删除文件失败", e);
return false;
}
}
/**
* 递归遍历出目录下面所有文件
*
* @param pathName 需要遍历的目录,必须以"/"开始和结束
* @throws IOException
*/
public static void list(FTPClient ftpClient, String pathName, List<String> arFiles) throws IOException {
ftpClient.enterLocalPassiveMode();
if (pathName.startsWith("/") && pathName.endsWith("/")) {
String directory = pathName;
//更换目录到当前目录
ftpClient.changeWorkingDirectory(directory);
FTPFile[] files = ftpClient.listFiles();
for (FTPFile file : files) {
if (file.isFile()) {
arFiles.add(directory + file.getName());
} else if (file.isDirectory()) {
list(ftpClient, directory + file.getName() + "/", arFiles);
}
}
}
}
/**
* 递归遍历目录下面指定的文件名
*
* @param pathName 需要遍历的目录,必须以"/"开始和结束
* @param ext 文件的扩展名
* @throws IOException
*/
public static void list(FTPClient ftpClient, String pathName, String ext, List<String> arFiles) throws IOException {
ftpClient.enterLocalPassiveMode();
if (pathName.startsWith("/") && pathName.endsWith("/")) {
String directory = pathName;
//更换目录到当前目录
ftpClient.changeWorkingDirectory(directory);
FTPFile[] files = ftpClient.listFiles();
for (FTPFile file : files) {
if (file.isFile()) {
if (file.getName().endsWith(ext)) {
arFiles.add(file.getName());
}
} else if (file.isDirectory()) {
list(ftpClient, directory + file.getName() + "/", ext, arFiles);
}
}
}
}
/**
* 上传文件
*
* @param pathname ftp服务保存地址
* @param fileName 上传到ftp的文件名
* @param originfilename 待上传文件的名称(绝对地址) *
* @return
*/
public static boolean uploadFile(FTPClient ftpClient, String pathname, String fileName, String originfilename) {
InputStream inputStream = null;
try {
log.info("开始上传文件");
ftpClient.enterLocalPassiveMode();
inputStream = new FileInputStream(new File(originfilename));
ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
ftpClient.changeWorkingDirectory(pathname);
ftpClient.storeFile(fileName, inputStream);
log.info("上传文件成功");
} catch (Exception e) {
log.info("上传文件失败" + e.getMessage(), e);
return false;
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
}
}
}
return true;
}
/**
* 上传文件
*
* @param pathname ftp服务保存地址 必须是绝对地址
* @param fileName 上传到ftp的文件名
* @param inputStream 输入文件流
* @return
*/
public static boolean uploadFile(FTPClient ftpClient, String pathname, String fileName, InputStream inputStream) {
try {
log.info("开始上传文件:{}/{}",pathname,fileName);
ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
ftpClient.changeWorkingDirectory(pathname);
ftpClient.storeFile(fileName, inputStream);
log.info("上传文件成功");
} catch (Exception e) {
log.info("上传文件失败:{}/{}" + e.getMessage(),pathname,fileName, e);
return false;
}
return true;
}
//创建多层目录文件,如果有ftp服务器已存在该文件,则不创建,如果无,则创建
public static boolean createDirectory(FTPClient ftpClient, String remote) throws IOException {
boolean success = true;
String directory = remote + "/";
// 如果远程目录不存在,则递归创建远程服务器目录
if (!directory.equalsIgnoreCase("/") && !ftpClient.changeWorkingDirectory(directory)) {
int start = 0;
int end = 0;
if (directory.startsWith("/")) {
start = 1;
} else {
start = 0;
}
end = directory.indexOf("/", start);
String path = "";
String paths = "";
while (true) {
String subDirectory = new String(remote.substring(start, end).getBytes("GBK"), "iso-8859-1");
path = path + "/" + subDirectory;
if (!existFile(ftpClient, path)) {
if (ftpClient.makeDirectory(subDirectory)) {
ftpClient.changeWorkingDirectory(subDirectory);
} else {
log.info("创建目录[" + subDirectory + "]失败");
ftpClient.changeWorkingDirectory(subDirectory);
}
} else {
ftpClient.changeWorkingDirectory(subDirectory);
}
paths = paths + "/" + subDirectory;
start = end + 1;
end = directory.indexOf("/", start);
// 检查所有目录是否创建完毕
if (end <= start) {
break;
}
}
}
return success;
}
//判断ftp服务器文件是否存在
public static boolean existFile(FTPClient ftpClient, String path) {
try {
FTPFile[] ftpFileArr = ftpClient.listFiles(path);
if (ftpFileArr != null && ftpFileArr.length > 0) {
return false;
}
return false;
} catch (Exception e) {
return false;
}
}
public static void close(FTPClient ftpClient) throws IOException {
if (ftpClient == null) {
return;
}
try {
if (ftpClient.isConnected()) {
ftpClient.logout();
ftpClient.disconnect();
}
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
public static class FTPServer {
private String ip;
private Integer port;
private String account;
private String pwd;
private String encoding;
public FTPServer() {
}
public FTPServer(String ip, Integer port, String account, String pwd, String encoding) {
this.ip = ip;
this.port = port;
this.account = account;
this.pwd = pwd;
this.encoding = encoding;
}
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public Integer getPort() {
return port;
}
public void setPort(Integer port) {
this.port = port;
}
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
public String getEncoding() {
return encoding;
}
public void setEncoding(String encoding) {
this.encoding = encoding;
}
}
}
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.55</version>
</dependency>
@Slf4j
public class SFTPUtils {
/**
* 连接,如果失败重试3次,间隔1s
*
* @param server
* @return
*/
public static ChannelSftp connectFtp(SFTPServer server) {
ChannelSftp sftp = null;
for (int i = 0; i < 3; i++) {
try {
log.info("connecting...ftp服务器:" + server.getIp() + ":" + server.getPort());
JSch jsch = new JSch();
Session sshSession = jsch.getSession(server.getAccount(), server.getIp(), server.getPort());
sshSession.setPassword(server.getPwd());
Properties sshConfig = new Properties();
sshConfig.put("StrictHostKeyChecking", "no");
sshSession.setConfig(sshConfig);
sshSession.connect();
Channel channel = sshSession.openChannel("sftp");
channel.connect();
sftp = (ChannelSftp) channel;
log.info("连接成功...ftp服务器" + server.getIp() + ":" + server.getPort());
break;
} catch (Exception e) {
try {
Thread.sleep(1000);
log.info("连接失败...ftp服务器" + server.getIp() + ":" + server.getPort() + ":" + e.getMessage(), e);
} catch (InterruptedException e1) {
log.error(e.getMessage(), e);
}
}
}
return sftp;
}
/**
* 下载文件 *
*
* @param pathname FTP服务器文件目录 *
* @param filename 文件名称 *
* @param localpath 下载后的文件路径 *
* @return
*/
public static void downloadFile(ChannelSftp sftp, String pathname, String filename, String localpath) {
if (StringUtils.isEmpty(pathname) || !pathname.endsWith("/")) {
throw new IllegalArgumentException("path is not illegal:" + pathname);
}
try (FileOutputStream outputStream = new FileOutputStream(localpath)) {
log.info("开始下载文件:{}", pathname + filename);
sftp.cd(pathname);
sftp.get(filename, outputStream);
log.info("文件已下载至{}", localpath);
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
/**
* 删除文件 *
*
* @param filename 要删除的文件名称 *
* @return
*/
public static boolean deleteFile(ChannelSftp sftp, String filename, String pathname) {
if (StringUtils.isEmpty(pathname) || !pathname.endsWith("/")) {
throw new IllegalArgumentException("path is not illegal:" + pathname);
}
try {
sftp.cd(pathname);
sftp.rm(filename);
log.info("已删除{}", pathname + filename);
return true;
} catch (Exception e) {
log.error(e.getMessage(), e);
}
return false;
}
/**
* 递归遍历出目录下面所有文件
*
* @param pathName 需要遍历的目录,必须以"/"开始和结束
* @throws IOException
*/
public static void list(ChannelSftp sftp, String pathName, List<String> arFiles) throws IOException {
if (StringUtils.isEmpty(pathName) || !pathName.endsWith("/")) {
return;
}
try {
sftp.cd(pathName);
Vector<String> files = sftp.ls("*");
for (int i = 0; i < files.size(); i++) {
Object obj = files.elementAt(i);
if (obj instanceof com.jcraft.jsch.ChannelSftp.LsEntry) {
ChannelSftp.LsEntry entry = (ChannelSftp.LsEntry) obj;
if (!entry.getAttrs().isDir()) {
String file = pathName + entry.getFilename();
arFiles.add(file);
} else {
if (!entry.getFilename().equals(".") && !entry.getFilename().equals("..")) {
String folder = pathName + entry.getFilename() + "/";
arFiles.add(folder);
list(sftp, folder, arFiles);
}
}
}
}
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
/**
* 递归遍历目录下面指定的文件名
*
* @param pathName 需要遍历的目录,必须以"/"开始和结束
* @param ext 文件的扩展名
* @throws IOException
*/
public static void list(ChannelSftp sftp, String pathName, String ext, List<String> arFiles) throws IOException {
if (StringUtils.isEmpty(pathName) || !pathName.endsWith("/")) {
return;
}
try {
sftp.cd(pathName);
Vector<String> files = sftp.ls("*");
for (int i = 0; i < files.size(); i++) {
Object obj = files.elementAt(i);
if (obj instanceof com.jcraft.jsch.ChannelSftp.LsEntry) {
ChannelSftp.LsEntry entry = (ChannelSftp.LsEntry) obj;
if (!entry.getAttrs().isDir()) {
if (entry.getFilename().endsWith(ext)) {
String file = pathName + entry.getFilename();
arFiles.add(file);
}
} else {
if (!entry.getFilename().equals(".") && !entry.getFilename().equals("..")) {
String folder = pathName + entry.getFilename() + "/";
arFiles.add(folder);
list(sftp, folder, arFiles);
}
}
}
}
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
/**
* 上传文件
*
* @param pathname ftp服务保存地址
* @param fileName 上传到ftp的文件名
* @param originfilename 待上传文件的名称(绝对地址) *
* @return
*/
public static boolean uploadFile(ChannelSftp sftp, String pathname, String fileName, String originfilename) {
if (StringUtils.isEmpty(pathname) || !pathname.endsWith("/")) {
throw new IllegalArgumentException("path is not illegal:" + pathname);
}
try (InputStream inputStream = new FileInputStream(new File(originfilename));) {
sftp.cd(pathname);
sftp.put(inputStream, fileName); //上传文件
log.info("上传文件成功:{},源文件:{}", pathname + fileName, originfilename);
return true;
} catch (Exception e) {
log.info("上传文件失败:{}" + e.getMessage(), pathname + fileName, e);
log.error(e.getMessage(), e);
return false;
}
}
/**
* 上传文件
*
* @param pathname ftp服务保存地址 必须是绝对地址
* @param fileName 上传到ftp的文件名
* @param inputStream 输入文件流
* @return
*/
public static boolean uploadFile(ChannelSftp sftp, String pathname, String fileName, InputStream inputStream) {
if (StringUtils.isEmpty(pathname) || !pathname.endsWith("/")) {
throw new IllegalArgumentException("path is not illegal:" + pathname);
}
try {
sftp.cd(pathname);
sftp.put(inputStream, fileName); //上传文件
log.info("上传文件成功:{}", pathname + fileName);
} catch (Exception e) {
log.info("上传文件失败:{}" + e.getMessage(), pathname + fileName, e);
return false;
}
return true;
}
/**
* 递归根据路径创建文件夹
*/
public static boolean createDirectory(ChannelSftp sftp, String remote) throws IOException {
if (StringUtils.isEmpty(remote) || !remote.endsWith("/")) {
throw new IllegalArgumentException("path is not illegal:" + remote);
}
try {
if (!existFolder(sftp, remote)) {
sftp.mkdir(remote);
}
log.info("创建目录成功:{}", remote);
return true;
} catch (Exception e) {
log.error(e.getMessage(), e);
}
return false;
}
//判断ftp服务器文件是否存在
public static boolean existFile(ChannelSftp sftp, String path) {
if (StringUtils.isEmpty(path) || path.endsWith("/")) {
throw new IllegalArgumentException("path is not illegal:" + path);
}
boolean isExist = false;
try {
SftpATTRS sftpATTRS = sftp.lstat(path);
isExist = true;
return !sftpATTRS.isDir();
} catch (Exception e) {
if (e.getMessage().toLowerCase().equals("no such file")) {
isExist = false;
}
}
return isExist;
}
public static boolean existFolder(ChannelSftp sftp, String path) {
if (StringUtils.isEmpty(path) || !path.endsWith("/")) {
throw new IllegalArgumentException("path is not illegal:" + path);
}
boolean isExist = false;
try {
SftpATTRS sftpATTRS = sftp.lstat(path);
isExist = true;
return sftpATTRS.isDir();
} catch (Exception e) {
if (e.getMessage().toLowerCase().equals("no such file")) {
isExist = false;
}
}
return isExist;
}
public static void close(ChannelSftp sftp) {
if (sftp == null) {
return;
}
try {
sftp.disconnect();
sftp.getSession().disconnect();
log.info("ftp连接已关闭");
} catch (JSchException e) {
log.error(e.getMessage(), e);
log.info("ftp连接关闭失败");
}
}
public static class SFTPServer {
private String ip;
private Integer port;
private String account;
private String pwd;
private String encoding;
public SFTPServer() {
}
public SFTPServer(String ip, Integer port, String account, String pwd, String encoding) {
this.ip = ip;
this.port = port;
this.account = account;
this.pwd = pwd;
this.encoding = encoding;
}
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public Integer getPort() {
return port;
}
public void setPort(Integer port) {
this.port = port;
}
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
public String getEncoding() {
return encoding;
}
public void setEncoding(String encoding) {
this.encoding = encoding;
}
}
}