提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
FtpUtil
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPFileFilter;
import org.apache.commons.net.ftp.FTPReply;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.SocketException;
import java.nio.charset.StandardCharsets;
public class FtpUtil {
private static final Logger logger = LoggerFactory.getLogger(FtpUtil.class);
private static final String SERVER_CHARSET = "ISO-8859-1";
//ftp对象
private FTPClient ftp;
private final String ip;
private final int port;
private final String name;
private final String pwd;
private String localCharset = "GBK";
public FtpUtil(String ip, int port, String name, String pwd) {
this.ip = ip;
this.port = port;
this.name = name;
this.pwd = pwd;
}
public void testConnect() {
getFtpClient();
}
/**
* 获取ftpclient初始方法
*/
private boolean getFtpClient() {
// 双重检索机制
if (ftp == null) {
synchronized (this) {
if (ftp == null) {
ftp = new FTPClient();
//验证登录
return connect();
}
}
} else if (!ftp.isConnected()) {
connect();
}
return ftp.isConnected();
}
private boolean connect() {
try {
ftp.connect(this.ip, this.port);
ftp.login(this.name, this.pwd);
if (!FTPReply.isPositiveCompletion(ftp.getReplyCode())) {
logger.info("【ftp用户名或密码错误】-连接失败!");
ftp.disconnect();
} else {
int reply;
reply = ftp.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
ftp.disconnect();
logger.info("【ftp连接失败】");
return false;
}
if (FTPReply.isPositiveCompletion(ftp.sendCommand("OPTS UTF8", "ON"))) {
// 开启服务器对UTF-8的支持,如果服务器支持就用UTF-8编码,否则就使用本地编码(GBK).
localCharset = "UTF-8";
}
ftp.setControlEncoding(localCharset);
ftp.setCharset(StandardCharsets.UTF_8);
ftp.setFileType(FTP.BINARY_FILE_TYPE);
ftp.enterLocalPassiveMode();
logger.info("【ftp连接成功】-文件编码采用:{}", localCharset);
return true;
}
} catch (IOException e) {
logger.warn("【获取ftp客户端连接异常】,异常堆栈:", e);
}
return false;
}
/**
* 从FTP服务器下载文件
*
* @param ftpPath FTP服务器中文件所在路径
* @param ftpFileName FTP服务器中文件名
* @param localPath 下载到本地的位置
* @param fileName 文件名称
*/
public boolean downloadFtpFile(String ftpPath, String ftpFileName, String localPath, String fileName) {
boolean isAppend = false;
OutputStream os = null;
try {
boolean flag = getFtpClient();
if (!flag) {
return false;
}
ftp.setFileTransferMode(FTPClient.STREAM_TRANSFER_MODE);
ftpPath = new String(ftpPath.getBytes(localCharset), SERVER_CHARSET);
ftp.changeWorkingDirectory(ftpPath);
logger.info("【当前ftp工作目录为】: {}", new String(ftp.printWorkingDirectory().getBytes(SERVER_CHARSET), localCharset));
File localFile = new File(localPath + File.separatorChar + fileName);
if(!localFile.exists()){
localFile.getParentFile().mkdirs();
}
os = new FileOutputStream(localFile);
isAppend = ftp.retrieveFile(new String(ftpFileName.getBytes(localCharset), SERVER_CHARSET), os);
logger.info("【下载ftp文件返回状态码】: {}", ftp.getReplyCode());
os.close();
ftp.logout();
if (isAppend) {
logger.info("【下载ftp文件成功】 文件名: {}", ftpFileName);
}else{
//文件不存在,删除本地文件
localFile.delete();
}
return isAppend;
} catch (FileNotFoundException e) {
logger.warn("【ftp文件不存在】,文件名称:{},文件路径:{},异常堆栈:", fileName, ftpPath, e);
} catch (SocketException e) {
logger.warn("【ftp连接失败】,异常堆栈:", e);
} catch (IOException e) {
logger.info("【下载ftp文件异常】,异常堆栈:", e);
} finally {
if (ftp.isConnected()) {
try {
ftp.disconnect();
} catch (IOException ioe) {
logger.info(ioe.getMessage(), ioe);
}
}
if (os != null) {
try {
os.close();
} catch (IOException ioe) {
logger.warn(ioe.getMessage(), ioe);
}
}
}
return isAppend;
}
/**
* Description: 向FTP服务器上传文件
*
* @param ftpPath FTP服务器中文件所在路径 格式: ftptest/aa
* @param tempName 上传过程中的文件名,有.now后缀
* @param fileName 上传完成的文件名
* @param input 文件流
* @return 成功返回true,否则返回false
*/
public boolean uploadFile(String ftpPath, String tempName, String fileName, InputStream input) {
boolean success = false;
try {
boolean flag = getFtpClient();
if (!flag) {
return false;
}
ftpPath = new String(ftpPath.getBytes(localCharset), SERVER_CHARSET);
ftp.makeDirectory(ftpPath);
ftp.changeWorkingDirectory(ftpPath);
logger.info("【当前ftp工作目录为】: {}", new String(ftp.printWorkingDirectory().getBytes(SERVER_CHARSET), localCharset));
tempName = new String(tempName.getBytes(localCharset), SERVER_CHARSET);
fileName = new String(fileName.getBytes(localCharset), SERVER_CHARSET);
success = ftp.storeFile(tempName, input);
logger.info("【上传ftp文件返回状态码】: {}", ftp.getReplyCode());
ftp.rename(tempName, fileName);
logger.info("【修改ftp文件名返回状态码】: {}", ftp.getReplyCode());
if (success) {
logger.info("【上传ftp文件成功】,文件名: {}", fileName);
}
ftp.logout();
} catch (IOException e) {
logger.warn("【上传文件至ftp异常】,文件名: {},异常堆栈:", fileName, e);
} finally {
if (ftp.isConnected()) {
try {
ftp.disconnect();
} catch (IOException ioe) {
logger.info(ioe.getMessage(), ioe);
}
}
if (input != null) {
try {
input.close();
} catch (IOException ioe) {
logger.warn(ioe.getMessage(), ioe);
}
}
}
return success;
}
/**
* Description: 向FTP服务器上传文件
*
* @param ftpPath FTP服务器中文件所在路径 格式: ftptest/aa
* @param fileName 上传完成的文件名
* @param input 文件流
* @return 成功返回true,否则返回false
*/
public boolean uploadFile(String ftpPath, String fileName, InputStream input) {
boolean success = false;
try {
boolean flag = getFtpClient();
if (!flag) {
return false;
}
ftpPath = new String(ftpPath.getBytes(localCharset), SERVER_CHARSET);
ftp.makeDirectory(ftpPath);
ftp.changeWorkingDirectory(ftpPath);
logger.info("【当前ftp工作目录为】: {}", new String(ftp.printWorkingDirectory().getBytes(SERVER_CHARSET), localCharset));
fileName = new String(fileName.getBytes(localCharset), SERVER_CHARSET);
success = ftp.storeFile(fileName, input);
logger.info("【上传ftp文件返回状态码】: {}", ftp.getReplyCode());
if (success) {
logger.info("【上传ftp文件成功】,文件名: {}", fileName);
}
ftp.logout();
} catch (IOException e) {
logger.warn("【上传文件至ftp异常】,文件名: {},异常堆栈:", fileName, e);
} finally {
if (ftp.isConnected()) {
try {
ftp.disconnect();
} catch (IOException ioe) {
logger.info(ioe.getMessage(), ioe);
}
}
if (input != null) {
try {
input.close();
} catch (IOException ioe) {
logger.warn(ioe.getMessage(), ioe);
}
}
}
return success;
}
/**
* 修改文件路径
*
* @param oldPath 原文件夹
* @param newPath 新的文件夹
* @param fileName 要移动的文件名称
* @return
*/
public boolean rename(String oldPath, String newPath, String fileName) {
boolean isAppend = false;
try {
boolean flag = getFtpClient();
if (!flag) {
return false;
}
oldPath = new String(oldPath.getBytes(localCharset), SERVER_CHARSET);
newPath = new String(newPath.getBytes(localCharset), SERVER_CHARSET);
ftp.changeWorkingDirectory(oldPath);
ftp.makeDirectory(newPath);
logger.info("【当前ftp工作目录为】: {}", new String(ftp.printWorkingDirectory().getBytes(SERVER_CHARSET), localCharset));
fileName = new String(fileName.getBytes(localCharset), SERVER_CHARSET);
isAppend = ftp.rename(fileName, newPath + "/" + fileName);
logger.info("【修改ftp文件目录返回状态码】: {}", ftp.getReplyCode());
if (isAppend) {
logger.info("【修改ftp文件目录文件成功】,文件名: {}", fileName);
}
ftp.logout();
} catch (Exception e) {
logger.warn("【修改ftp文件目录异常】,文件名: {},异常堆栈:", fileName, e);
} finally {
if (ftp.isConnected()) {
try {
ftp.disconnect();
} catch (IOException ioe) {
logger.info(ioe.getMessage(), ioe);
}
}
}
return isAppend;
}
/**
* 修改文件名
*
* @param oldFileName 原文件名
* @param newFileName 新的文件名
* @param filePath 文件夹路径
* @return
*/
public boolean renameFile(String oldFileName, String newFileName, String filePath) {
boolean isAppend = false;
try {
boolean flag = getFtpClient();
if (!flag) {
return false;
}
oldFileName = new String(oldFileName.getBytes(localCharset), SERVER_CHARSET);
newFileName = new String(newFileName.getBytes(localCharset), SERVER_CHARSET);
filePath = new String(filePath.getBytes(localCharset), SERVER_CHARSET);
ftp.changeWorkingDirectory(filePath);
logger.info("【当前ftp工作目录为】: {}", new String(ftp.printWorkingDirectory().getBytes(SERVER_CHARSET), localCharset));
isAppend = ftp.rename(oldFileName, newFileName);
logger.info("【重命名ftp文件返回状态码】: {}", ftp.getReplyCode());
logger.info("【修改ftp文件目录返回状态码】: {}", ftp.getReplyCode());
if (isAppend) {
logger.info("【重命ftp文件名成功】,旧文件名:{},新文件名: {}", oldFileName, newFileName);
}
ftp.logout();
} catch (Exception e) {
logger.warn("【重命ftp文件名失败】,异常堆栈:", e);
} finally {
if (ftp.isConnected()) {
try {
ftp.disconnect();
} catch (IOException ioe) {
logger.info(ioe.getMessage(), ioe);
}
}
}
return isAppend;
}
/**
* 删除ftp 文件
**/
public boolean delete(String ftpPath, String fileName) {
try {
boolean flag = getFtpClient();
if (!flag) {
return false;
}
ftp.setFileTransferMode(FTPClient.STREAM_TRANSFER_MODE);
ftpPath = new String(ftpPath.getBytes(localCharset), SERVER_CHARSET);
fileName = new String(fileName.getBytes(localCharset), SERVER_CHARSET);
ftp.changeWorkingDirectory(ftpPath);
logger.info("【当前ftp工作目录为】: {}", new String(ftp.printWorkingDirectory().getBytes(SERVER_CHARSET), localCharset));
logger.info("【要删除的ftp文件名称】:{}", fileName);
boolean deleted = ftp.deleteFile(fileName);
if (deleted)
logger.info("【删除ftp文件成功】,文件路径:{},文件名称:{}", ftpPath, fileName);
else
logger.warn("【删除ftp文件失败】,文件路径:{},文件名称:{}", ftpPath, fileName);
ftp.logout();
return deleted;
} catch (Exception e) {
logger.warn("【删除ftp文件异常】,文件路径:{},文件名称:{},异常堆栈:", ftpPath, fileName, e);
return false;
} finally {
if (ftp.isConnected()) {
try {
ftp.disconnect();
} catch (IOException ioe) {
logger.warn(ioe.getMessage(), ioe);
}
}
}
}
/**
* 删除ftp 目录
**/
public boolean deleteDir(String ftpPath, String dirName) {
try {
boolean flag = getFtpClient();
if (!flag) {
return false;
}
ftp.setFileTransferMode(FTPClient.STREAM_TRANSFER_MODE);
ftpPath = new String(ftpPath.getBytes(localCharset), SERVER_CHARSET);
dirName = new String(dirName.getBytes(localCharset), SERVER_CHARSET);
ftp.changeWorkingDirectory(ftpPath);
logger.info("【当前ftp工作目录为】: {}", new String(ftp.printWorkingDirectory().getBytes(SERVER_CHARSET), localCharset));
logger.info("【要删除的ftp目录】:{}", dirName);
boolean deleted = ftp.removeDirectory(dirName);
if (deleted)
logger.info("【删除ftp目录成功】,文件路径:{},目录名称:{}", ftpPath, dirName);
else
logger.warn("【删除ftp目录失败】,文件路径:{},目录名称:{}", ftpPath, dirName);
ftp.logout();
return deleted;
} catch (Exception e) {
logger.warn("【删除ftp目录异常】,文件路径:{},目录名称:{},异常堆栈:", ftpPath, dirName, e);
return false;
} finally {
if (ftp.isConnected()) {
try {
ftp.disconnect();
} catch (IOException ioe) {
logger.warn(ioe.getMessage(), ioe);
}
}
}
}
/**
* 获取ftp服务器上某个文件夹下的全部文件
**/
public FTPFile[] listFile(String ftpPath, FTPFileFilter ftpFileFilter) {
try {
boolean flag = getFtpClient();
if (!flag) {
return null;
}
ftp.changeWorkingDirectory(ftpPath);
return ftp.listFiles(ftpPath, ftpFileFilter);
} catch (Exception e) {
logger.warn("【列举ftp目录异常】,文件路径:{},异常堆栈:", ftpPath, e);
return null;
} finally {
if (ftp.isConnected()) {
try {
ftp.disconnect();
} catch (IOException ioe) {
logger.warn(ioe.getMessage(), ioe);
}
}
}
}
}
应用
1.向FTP服务器上传文件
FtpUtil ftpUtil = new FtpUtil(cdmsWsapFtpProperties.getIp(),
cdmsWsapFtpProperties.getPort(),
cdmsWsapFtpProperties.getUser(),
cdmsWsapFtpProperties.getPwd());
File file =new File();
String tempName = uploadFileName + ".now";
boolean uploadOk = ftpUtil.uploadFile(cdmsWsapFtpProperties.getUploadDir(),
tempName, uploadFileName, new BufferedInputStream(new FileInputStream(file)));
if (uploadOk) {
logger.info("文件【{}】上传到【{} {}】成功",uploadFileName, cdmsWsapFtpProperties.getIp(), cdmsWsapFtpProperties.getUploadDir());
//id自增
Long increment = redisUtil.increment(redisBatch);
//更新t_personal_subscribe_wsap status 为 1
updateStatus(wsapModelList);
} else {
logger.info("文件【{}】上传到【{} {}】失败",uploadFileName, cdmsWsapFtpProperties.getIp(), cdmsWsapFtpProperties.getUploadDir());
}
2.修改文件路径
private void moveFtpFile(String fileName) {
try {
FtpUtil ftpUtil = new FtpUtil(adaFtpFileProperties.getFtpIp(), adaFtpFileProperties.getFtpPort(), adaFtpFileProperties.getFtpUsername(), adaFtpFileProperties.getFtpPwd());
boolean rename = ftpUtil.rename(adaFtpFileProperties.getFtpDir(), adaFtpFileProperties.getBackupDir(), fileName);
if (rename) {
log.info("将文件 {} 移动到备份目录 {} 成功", fileName, adaFtpFileProperties.getBackupDir());
} else {
log.warn("将文件 {} 移动到备份目录 {} 失败", fileName, adaFtpFileProperties.getBackupDir());
}
} catch (Exception e) {
log.warn("移动文件异常", e);
}
}
3.删除ftp上的文件
/**
* 只保留最近15天的ftp文件
**/
private void doClearTmpFile() {
logger.info("[对私客户信息] 删除本地文件3天前下载的文件开始");
try {
// 取当前文件名称的前缀
final int domIndex = tdiipProperties.getTdiipFormat().indexOf(".");
String startWith = tdiipProperties.getTdiipFormat().substring(0, domIndex);
// ===============1. 删除ftp上的文件=================
FtpUtil ftpUtil = new FtpUtil(tdiipProperties.getFtpIp(), tdiipProperties.getFtpPort(), tdiipProperties.getFtpUsername(), tdiipProperties.getFtpPwd());
String targetPath = tdiipProperties.getBackupDir();
LocalDate ftpBoundary = LocalDate.now().minusDays(DcdsFileConstants.SAVE_FILE_DAYS);
final FTPFile[] ftpDeleteFiles = ftpUtil.listFile(targetPath, ftpFile -> {
logger.info("[对私客户信息] ftp文件扫描开始,文件名:{}", ftpFile.getName());
try {
int len = ftpFile.getName().length();
String dateString = ftpFile.getName().substring(len - 9, len - 1);
LocalDate fileDate = LocalDate.parse(dateString, DateTimeFormatter.ofPattern("yyyyMMdd"));
return ftpFile.getName().startsWith(startWith) && (fileDate.isBefore(ftpBoundary) || fileDate.isEqual(ftpBoundary));
} catch (Exception ignore) {
return false;
}
});
if (ftpDeleteFiles != null && ftpDeleteFiles.length > 0) {
for (FTPFile file : ftpDeleteFiles) {
if (ftpUtil.delete(targetPath, file.getName())) {
logger.info("[对私客户信息] ftp文件删除成功,文件名:{}", file.getName());
} else {
logger.warn("[对私客户信息] ftp文件删除失败,文件名:{}", file.getName());
}
}
}
// ===============2. 删除本地的文件=====================
File localTmpDir = new File(tdiipProperties.getLocalTmpDir());
if (!localTmpDir.exists())
return;
File[] files = null;
if (localTmpDir.isDirectory()) {
files = localTmpDir.listFiles();
}
if (files == null || files.length == 0)
return;
// 取删除日期的边界线
LocalDate localBoundary = LocalDate.now();
for (File file : files) {
String fileName = file.getName();
if (!fileName.startsWith(startWith))
continue;
int len = file.getName().length();
try {
String dateString = fileName.substring(len - 9, len - 1);
LocalDate fileDate = LocalDate.parse(dateString, DateTimeFormatter.ofPattern("yyyyMMdd"));
if ((fileDate.isBefore(localBoundary) || fileDate.isEqual(localBoundary)) && file.delete()) {
logger.info("[对私客户信息] 本地文件删除完成,文件名:{}", file.getName());
}
} catch (Exception ignore) {
logger.warn("[对私客户信息] 本地文件删除失败,文件名:{}", file.getName());
}
}
} catch (Exception e) {
logger.error("[对私客户信息] 文件删除异常:", e);
} finally {
logger.info("[对私客户信息] 删除本地文件15天前下载的文件结束");
}
}