对ftp文件上传将行封装,实现连接的单例模式,完成线程安全的改进,ftp文件上传下载失败的重试。
application.yml配置文件
ftp:
ip: 127.0.0.1
port: 21
username: admin
password: admin
downloadSleep: 100 #文件下载失败下次超时重试时间
downloadRetry: 10 #文件下载失败重试次数
uploadSleep: 100 #文件上传失败下次超时重试时间
uploadRettry: 10 #文件上传失败重试次数
FTPClientUtils.java
包含ftp文件上传的一些基本方法,单个上传,批量下载,单个文件下载
/**
* FTP文件上传下载工具类
* @author 奇点_
*
*/
@Component
@ConfigurationProperties(prefix = "ftp")
public class FTPClientUtils {
private static int downloadSleep;
private static int downloadRetry;
private static int uploadSleep;
private static int uploadRettry;
private static Logger LOGGER = LoggerFactory.getLogger(FTPClientUtils.class);
/**
*
* @param ftpPath 上传到ftp的路径
* @param file 上传到ftp的文件对象
* @return boolean true上传文件成功 false 上传文件失败
*/
public static boolean doUpLoad(String ftpPath,File file){
boolean result=false;
Integer i = 0;
while(!result){
FTPClient client = FTPConnectionFactory.getInstance().makeConnection();
try {
try {
client.changeDirectory(ftpPath);
} catch (Exception e) {
LOGGER.error("ftp文件目录不存在:"+ftpPath);
}
client.upload(file);
if(i>0){
LOGGER.info("ftp重试文件上传成功,ftp路径:"+ftpPath+",文件名称:"+file.getName());
}else{
LOGGER.info("ftp文件上传成功,ftp路径为"+ftpPath+",文件名称:"+file.getName());
}
result = true;
}catch (Exception e) {
i++;
LOGGER.error("ftp文件上传失败,重试中。。。第"+i+"次,错误信息"+e.getMessage());
if(i>uploadRettry){
LOGGER.error("ftp文件上传失败,超过重试次数结束重试,错误信息"+e.getMessage());
return result;
}
try {
TimeUnit.MILLISECONDS.sleep(uploadSleep);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
}
return result;
}
/**
*
* @param ftpPath 要下载的文件在ftp中的路径
* @param fileName 要下载的文件名称
* @param localPath 文件要下载的路径
* @return false 下载失败 true 下载成功
*/
public static boolean doDownLoad(String ftpPath,String fileName,String localPath){
boolean result=false;
Integer i = 0;
while(!result){
FTPClient client = FTPConnectionFactory.getInstance().makeConnection();
try {
client.changeDirectory(ftpPath);
client.download(fileName, new File(localPath+"/"+fileName));
if(i>0){
LOGGER.info("ftp文件重试下载成功,ftp地址:"+ftpPath+",文件名称:"+fileName+"本地文件地址:"+localPath);
}else{
LOGGER.info("ftp文件下载成功,ftp地址:"+ftpPath+",文件名称:"+fileName+"本地文件地址:"+localPath);
}
result = true;
}catch (Exception e) {
i++;
LOGGER.error("ftp文件下载失败,重试中。。。第"+i+"次,错误信息ftp地址:"+ftpPath+",文件名称:"+fileName+"本地文件地址:"+localPath+e.getMessage());
if(i>downloadRetry){
LOGGER.error("ftp文件下载失败,超过重试次数结束重试,错误信息ftp地址:"+ftpPath+",文件名称:"+fileName+"本地文件地址:"+localPath+e.getMessage());
return result;
}
try {
TimeUnit.MILLISECONDS.sleep(downloadSleep);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
}
return result;
}
/**
*
* @param ftpPath 下载该目录下的所有文件,不包括文件夹
* @param localPath 下载到本地的目录
* @return true 下载成功 false 下载失败
*/
public static boolean doDownLoad(String ftpPath,String localPath){
boolean result=false;
FTPClient client = FTPConnectionFactory.getInstance().makeConnection();
try {
client.changeDirectory(ftpPath);
FTPFile[] fileNames = client.list();
for (FTPFile ftpFile : fileNames) {
if(ftpFile.getType()==FTPFile.TYPE_FILE){
try {
doDownLoad(ftpPath,ftpFile.getName(),localPath);
} catch (Exception e) {
}
}
}
result = true;
}catch (Exception e) {
LOGGER.error("ftp文件批量下载失败,错误信息"+e.getMessage());
}
return result;
}
/**
* 判断一个FTP路径是否存在,如果存在返回类型(FTPFile.TYPE_DIRECTORY=1、FTPFile.TYPE_FILE=0、FTPFile.TYPE_LINK=2)
* 如果文件不存在,则返回一个-1
* @param ftpPath FTP文件或文件夹路径
* @return 存在时候返回类型值(文件0,文件夹1,链接2),不存在则返回-1
*/
public static int isExist(String ftpPath){
FTPClient client = FTPConnectionFactory.getInstance().makeConnection();
FTPFile[] list = null;
try {
list = client.list(ftpPath);
} catch (Exception e) {
return -1;
}
if (list.length > 1) return FTPFile.TYPE_DIRECTORY;
else if (list.length == 1) {
FTPFile f = list[0];
if (f.getType() == FTPFile.TYPE_DIRECTORY) return FTPFile.TYPE_DIRECTORY;
String _path = ftpPath +File.separator+ f.getName();
try {
int y = client.list(_path).length;
if (y == 1) return FTPFile.TYPE_DIRECTORY;
else return FTPFile.TYPE_FILE;
} catch (Exception e) {
return -1;
}
} else {
try {
client.changeDirectory(ftpPath);
return FTPFile.TYPE_DIRECTORY;
} catch (Exception e) {
return -1;
}
}
}
/**
*
* @param ftpPath 递归下载该目录下的所有文件。
* @param localPath 下载到本地的目录
* @return true 下载成功 false 下载失败
*/
public synchronized static boolean doDownLoadAll(String ftpPath,String localPath){
boolean result=false;
FTPClient client = FTPConnectionFactory.getInstance().makeConnection();
try {
client.changeDirectory(ftpPath);
FTPFile[] fileNames = client.list();
for (FTPFile ftpFile : fileNames) {
if(ftpFile.getType()==FTPFile.TYPE_FILE){
try {
doDownLoad(ftpPath, localPath);
} catch (Exception e) {
}
}
if(ftpFile.getType()==FTPFile.TYPE_DIRECTORY){
String path = localPath+"/"+ftpFile.getName();
File file = new File(path);
if(!file.exists()){
file.mkdirs();
}
doDownLoadAll(ftpPath+"/"+ftpFile.getName(), path);
}
}
result = true;
}catch (Exception e) {
LOGGER.error("ftp文件批量下载失败,错误信息"+e.getMessage());
}
return result;
}
/**
*
* @param ftpPath ftp的文件路径
* @param localPath 文件下载到的本地路径
* @param ftpPathBak
* @param isDeleteFile 下载后是否删除文件,传入true or false
* @param isBakFile
* @return
*/
public static boolean doDownLoad(String ftpPath, String localPath, String ftpPathBak, String isDeleteFile, String isBakFile) {
boolean result=false;
Integer k = 0;
while(!result){
FTPClient client = FTPConnectionFactory.getInstance().makeConnection();
try {
client.changeDirectory(ftpPath);
String[] fileNames = client.listNames();
for (int i = 0; i < fileNames.length; i++) {
File file = new File(localPath+ fileNames[i]);
client.download(fileNames[i], file);
if (isBakFile.equals("true")){
client.rename(fileNames[i], ftpPathBak+fileNames[i]);
}
if (isDeleteFile.equals("true")){
client.deleteFile(fileNames[i]);
}
}
if(k>0){
LOGGER.info("ftp文件重试下载成功,ftp地址:"+ftpPath+",本地文件地址:"+localPath);
}else{
LOGGER.info("ftp文件下载成功,ftp地址:"+ftpPath+"本地文件地址:"+localPath);
}
result = true;
} catch (Exception e) {
k++;
LOGGER.error("ftp文件下载失败,重试中。。。第"+k+"次,错误信息"+e.getMessage());
if(k>downloadRetry){
return result;
}
try {
TimeUnit.MILLISECONDS.sleep(downloadSleep);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
}
return result;
}
public static int getDownloadSleep() {
return downloadSleep;
}
public static void setDownloadSleep(int downloadSleep) {
FTPClientUtils.downloadSleep = downloadSleep;
}
public static int getDownloadRetry() {
return downloadRetry;
}
public static void setDownloadRetry(int downloadRetry) {
FTPClientUtils.downloadRetry = downloadRetry;
}
public static int getUploadSleep() {
return uploadSleep;
}
public static void setUploadSleep(int uploadSleep) {
FTPClientUtils.uploadSleep = uploadSleep;
}
public static int getUploadRettry() {
return uploadRettry;
}
public static void setUploadRettry(int uploadRettry) {
FTPClientUtils.uploadRettry = uploadRettry;
}
}
SFTPConnectionFactory.java
是生成sftp上传对象的工场类
@Component
@ConfigurationProperties(prefix = "ftp")
public class FTPConnectionFactory {
private static Logger LOGGER = LoggerFactory.getLogger(FTPClientUtils.class);
/** FTP ip地址*/
private static String ip;
/** FTP 端口号*/
private static int port;
/** FTP 设置字符集*/
private static String charset;
/** FTP 用户名*/
private static String username;
/** FTP 密码*/
private static String password;
private static final FTPConnectionFactory factory = new FTPConnectionFactory();
private FTPClient client;
private FTPConnectionFactory(){
}
public static FTPConnectionFactory getInstance(){
return factory;
}
synchronized public FTPClient makeConnection(){
if(client==null||!client.isConnected()){
try {
client = new FTPClient();
client.connect(ip, port);
client.setCharset(charset);
client.login(username, password);
} catch (Exception e) {
LOGGER.error("ftp登录失败,检测登录ip,端口号,用户名密码是否正确,错误信息为"+e.getMessage());
}
LOGGER.info("ftp服务器连接成功");
}
return client;
}
/**
* 关闭连接 server
*/
public void logout(){
if (client != null) {
if (client.isConnected()) {
try {
client.disconnect(false);
} catch (Exception e) {
LOGGER.error("ftp连接断开失败,错误信息"+e.getMessage());
};
}
}
}
public static String getIp() {
return ip;
}
public static void setIp(String ip) {
FTPConnectionFactory.ip = ip;
}
public static int getPort() {
return port;
}
public static void setPort(int port) {
FTPConnectionFactory.port = port;
}
public static String getCharset() {
return charset;
}
public static void setCharset(String charset) {
FTPConnectionFactory.charset = charset;
}
public static String getUsername() {
return username;
}
public static void setUsername(String username) {
FTPConnectionFactory.username = username;
}
public static String getPassword() {
return password;
}
public static void setPassword(String password) {
FTPConnectionFactory.password = password;
}
}
pom.xml 依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>fakepath</groupId>
<artifactId>ftp4j</artifactId>
<version>1.7.2</version>
</dependency>
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.54</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
</dependencies>