对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>