ftp连接池实现

spring所需要的jar包我就不给你们了,你们自行搭建spring项目架构,或者使用springboot构建方便省事。我就直接上代码了。

1.ftp.properties

ftp.host=127.0.0.1
ftp.username=HQ
ftp.password=HQ
ftp.port=21

2.解析ftp.properties文件,首先创建一个FtpClientConfig类,用于存储ftp.properties中的数值,@PropertySource注解用于解析ftp.properties;@Value("${ftp.host}")将ftp.properties中的ftp.host的值注入到FtpClientConfig的host字段中。其中遇到了一个问题就是注入到host中的是${ftp.host},而不是ftp.host对应的值,百度了好久才查到是因为占位符的原因,需要在获得FtpClientConfig的实例前,将PropertySourcesPlaceholderConfigurer注入到容器中,这时占位符才有效。

package com.chen.ftp;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;

/**
*@author  chenmin
*@version 创建时间:2020年5月27日 下午4:26:56
*
*/
@Component
@PropertySource(value={"classpath:config/ftp.properties"})
public class FtpClientConfig {

	@Value("${ftp.host}")
	private String host;
	
	@Value("${ftp.port}")
	private String port;
	
	@Value("${ftp.username}")
	private String username;
	
	@Value("${ftp.password}")
	private String password;

	public String getHost() {
		return host;
	}

	public String getPort() {
		return port;
	}

	public String getUsername() {
		return username;
	}

	public String getPassword() {
		return password;
	}
	
	@Override
	public String toString() {
		return host+"\t"+port;
	}
	
}

3.MyConfiguration.java,配置类,相当于spring.xml文件,将PropertySourcesPlaceholderConfigurer注入容器中

package com.chen.ftp;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;

@Configuration
public class MyConfiguration {

	@Bean
	public PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer(){
		return new PropertySourcesPlaceholderConfigurer();
	}
}

4.FtpClientFactory.java,FtpClient工厂类,创建FtpClient,销毁FtpClient,检测ftp连接

package com.chen.ftp;

import org.apache.commons.net.ftp.FTPClient;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
*@author  chenmin
*@version 创建时间:2020年5月27日 下午4:27:25
*
*/
@Component
public class FtpClientFactory {

	private Logger logger = Logger.getLogger(FtpClientFactory.class);
	
	@Autowired
	private FtpClientConfig ftpClientConfig;
	
	public FTPClient makeFtpClient() throws Exception{
		FTPClient ftpClient = new FTPClient();
		ftpClient.setConnectTimeout(1000*10);
		try{
			ftpClient.connect(ftpClientConfig.getHost(), Integer.parseInt(ftpClientConfig.getPort()));
			boolean result = ftpClient.login(ftpClientConfig.getUsername(), ftpClientConfig.getPassword());
			if(!result){
				logger.info("ftp登录失败,username:"+ftpClientConfig.getUsername());
				return null;
			}
			ftpClient.setControlEncoding("utf-8");
			ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
			ftpClient.enterLocalActiveMode();
			ftpClient.enterLocalPassiveMode();//这一句很重要!!!下面进行解释
		}catch(Exception e){
			logger.error("makeClient exception", e);
			//销毁ftpClient
			destroyClient(ftpClient);
		}
		
		return ftpClient;
	}
	
	public void destroyClient(FTPClient ftpClient){
		try {
			if(ftpClient != null && ftpClient.isConnected()){
				ftpClient.disconnect();
			}
		} catch (Exception e) {
			logger.error("ftpClient logout exception", e);
		}finally {
			try {
				if(ftpClient != null){
					ftpClient.disconnect();
				}
			} catch (Exception e2) {
				logger.error("ftpClient disconnect exception", e2);
			}
		}
	}
	
	//监测ftp连接
	public boolean validateClient(FTPClient ftpClient){
		try {
			return ftpClient.sendNoOp();
		} catch (Exception e) {
			logger.error("ftpClient validate exception",e);
		}
		return false;
	}
}

5.FtpClientPool.java,ftpClient连接池,初始化,获取ftpClient,将ftpClient放回连接池

package com.chen.ftp;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;

import org.apache.commons.net.ftp.FTPClient;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
*@author  chenmin
*@version 创建时间:2020年5月29日 上午9:10:42
*
*/
@Component
public class FtpClientPool {

	private static final int DEFAULT_POOL_SIZE = 5;
	
	private BlockingQueue<FTPClient> pool;
	
	@Autowired
	private FtpClientFactory factory;
	
	private Logger logger = Logger.getLogger(FtpClientPool.class);
	
	public FtpClientPool(){
		
	}
	
	public FtpClientPool(FtpClientFactory factory){
		this(factory, DEFAULT_POOL_SIZE);
	}
	
	public FtpClientPool(FtpClientFactory factory,int size){
		this.factory = factory;
		this.pool = new ArrayBlockingQueue<FTPClient>(size);
		initPool(size);
	}
	
	//初始化
	private void initPool(int maxPoolSize){
		try {
			int count = 0;
			while(count < maxPoolSize){
				pool.offer(factory.makeFtpClient(),10,TimeUnit.SECONDS);
				count++;
			}
		} catch (Exception e) {
			logger.error("ftp连接池初始化失败", e);
		}
	}
	
	//从阻塞队列中获取一个ftp连接
	public FTPClient borrowClient() throws Exception{
		FTPClient ftpClient = pool.take();
		if(ftpClient == null){
			ftpClient = factory.makeFtpClient();
			//归还对象,即把ftpClient放到连接池中
			returnFtpClient(ftpClient);
		}else if(!factory.validateClient(ftpClient)){
			ftpClient = factory.makeFtpClient();
			returnFtpClient(ftpClient);
		}
		return ftpClient;
	}
	
	//归还一个ftp连接
	public void returnFtpClient(FTPClient ftpClient) throws Exception{
		try {
			if(ftpClient != null && !pool.offer(ftpClient,10,TimeUnit.SECONDS)){
				factory.destroyClient(ftpClient);
			}
		} catch (Exception e) {
			logger.error("归还对象失败", e);
		}
	}
	
	
	public int getPoolSize(){
		return pool.size();
	}
}

6.FtpUtil.java

package com.chen.ftp;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

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.FTPReply;

/**
 * ftp上传下载工具类
 * <p>Title: FtpUtil</p>
 * <p>Description: </p>
 * <p>Company: www.itcast.com</p> 
 * @author	入云龙
 * @date	2015年7月29日下午8:11:51
 * @version 1.0
 */
public class FtpUtil {

	/** 
	 * Description: 向FTP服务器上传文件 
	 * @param host FTP服务器hostname 
	 * @param port FTP服务器端口 
	 * @param username FTP登录账号 
	 * @param password FTP登录密码 
	 * @param basePath FTP服务器基础目录
	 * @param filePath FTP服务器文件存放路径。例如分日期存放:/2015/01/01。文件的路径为basePath+filePath
	 * @param filename 上传到FTP服务器上的文件名 
	 * @param input 输入流 
	 * @return 成功返回true,否则返回false 
	 */  
	public static boolean uploadFile(String host, int port, String username, String password, String basePath,
			String filePath, String filename, InputStream input) {
		boolean result = false;
		FTPClient ftp = new FTPClient();
		try {
			int reply;
			ftp.connect(host, port);// 连接FTP服务器
			// 如果采用默认端口,可以使用ftp.connect(host)的方式直接连接FTP服务器
			ftp.login(username, password);// 登录
			reply = ftp.getReplyCode();
			if (!FTPReply.isPositiveCompletion(reply)) {
				ftp.disconnect();
				return result;
			}
			//切换到上传目录
			if (!ftp.changeWorkingDirectory(basePath+filePath)) {
				//如果目录不存在创建目录
				String[] dirs = filePath.split("/");
				String tempPath = basePath;
				for (String dir : dirs) {
					if (null == dir || "".equals(dir)) continue;
					tempPath += "/" + dir;
					if (!ftp.changeWorkingDirectory(tempPath)) {
						if (!ftp.makeDirectory(tempPath)) {
							return result;
						} else {
							ftp.changeWorkingDirectory(tempPath);
						}
					}
				}
			}
			//设置上传文件的类型为二进制类型
			ftp.setFileType(FTP.BINARY_FILE_TYPE);
			//上传文件
			if (!ftp.storeFile(filename, input)) {
				return result;
			}
			input.close();
			ftp.logout();
			result = true;
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (ftp.isConnected()) {
				try {
					ftp.disconnect();
				} catch (IOException ioe) {
				}
			}
		}
		return result;
	}
	
	/** 
	 * Description: 从FTP服务器下载文件 
	 * @param host FTP服务器hostname 
	 * @param port FTP服务器端口 
	 * @param username FTP登录账号 
	 * @param password FTP登录密码 
	 * @param remotePath FTP服务器上的相对路径 
	 * @param fileName 要下载的文件名 
	 * @param localPath 下载后保存到本地的路径 
	 * @return 
	 */  
	public static boolean downloadFile(String host, int port, String username, String password, String remotePath,
			String fileName, String localPath) {
		boolean result = false;
		FTPClient ftp = new FTPClient();
		try {
			int reply;
			ftp.connect(host, port);
			// 如果采用默认端口,可以使用ftp.connect(host)的方式直接连接FTP服务器
			ftp.login(username, password);// 登录
			reply = ftp.getReplyCode();
			if (!FTPReply.isPositiveCompletion(reply)) {
				ftp.disconnect();
				return result;
			}
			ftp.changeWorkingDirectory(remotePath);// 转移到FTP服务器目录
			FTPFile[] fs = ftp.listFiles();
			for (FTPFile ff : fs) {
				if (ff.getName().equals(fileName)) {
					File localFile = new File(localPath + "/" + ff.getName());

					OutputStream is = new FileOutputStream(localFile);
					ftp.retrieveFile(ff.getName(), is);
					is.close();
				}
			}

			ftp.logout();
			result = true;
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (ftp.isConnected()) {
				try {
					ftp.disconnect();
				} catch (IOException ioe) {
				}
			}
		}
		return result;
	}
	
	/**
	 * 
	 * @param ftpClient
	 * @param fileName_pattern		文件名称的正则,用于筛选文件
	 * @param remotePath	ftp的目录文件夹
	 * @param localPath		下载到本地的文件地址
	 * @return
	 * @throws IOException
	 */
	public static boolean downLoadFile(FTPClient ftpClient,String fileName_pattern,String remotePath,String localPath) throws IOException{
		boolean result = false;
		
		int reply = ftpClient.getReplyCode();
		if (!FTPReply.isPositiveCompletion(reply)) {
			ftpClient.disconnect();
			return result;
		}
		ftpClient.changeWorkingDirectory(remotePath);// 转移到FTP服务器目录
		FTPFile[] fs = ftpClient.listFiles();
		for (FTPFile ff : fs) {
			//查找对应的文件
			boolean flag = checkFileName(ff.getName(), fileName_pattern);
			if (flag) {
				File localFile = new File(localPath + "/" + ff.getName());

				OutputStream is = new FileOutputStream(localFile);
				ftpClient.retrieveFile(ff.getName(), is);
				is.close();
			}
		}
		
		return true;
	}
	
	/**
	 * 
	 * @param ftpClient
	 * @param fileName
	 * @param remotePath
	 * @return
	 * @throws IOException
	 */
	public static boolean deleteFile(FTPClient ftpClient,String fileName,String remotePath) throws IOException{
		boolean result = false;
		
		int reply = ftpClient.getReplyCode();
		if(!FTPReply.isPositiveCompletion(reply)){
			ftpClient.disconnect();
			return result;
		}
		
		result = ftpClient.deleteFile(fileName);
		
		return result;
	}
	
	/**
	 * 使用正则表达式比较这两个字符串是否匹配
	 * @param filename	文件名
	 * @param pattern	比较规则		"^ksswxryxx\\d*\\.xml$"
	 * @return
	 */
	public static boolean checkFileName(String filename,String pattern){
		Pattern p = Pattern.compile(pattern);
		Matcher m = p.matcher(filename);
		if (m.find()){
			return true;
		}
		return false;
	}
}

7.FtpTest.java

package com.chen.ftp;

import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
import org.apache.log4j.Logger;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
*@author  chenmin
*@version 创建时间:2020年5月29日 上午9:40:04
*
*/
public class FtpTest {

	private Logger logger = Logger.getLogger(FtpTest.class);
	
	@Test
	public void test01(){
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
		
		// 注解扫描,和@ComponentScan 和 基于XML的配置<context:component-scan base-package>相同
        context.scan("com.chen.ftp");
		
        // 刷新上下文环境
        context.refresh();
        
		FtpClientFactory ftpClientFactory = context.getBean(FtpClientFactory.class);
		
		FtpClientPool ftpClientPool = new FtpClientPool(ftpClientFactory);
		
		FTPClient ftpClient = null;
		try {
			ftpClient = ftpClientPool.borrowClient();
			
			//通过ftp读取文件,下载符合正则的所有文件
			boolean result = FtpUtil.downLoadFile(ftpClient, "^ksswxryxx\\d*\\.xml$", "/", "D:/FTP/data");
			if(result){
				logger.info("下载成功!");
				//删除ftp上的文件---具体删除某个文件
				if(FtpUtil.deleteFile(ftpClient, "ksswxryxx20190909202146.xml", "/")){
					logger.info("删除ftp上的文件成功!");
				}else{
					logger.info("删除ftp上的文件失败!");
				}
			}else{
				logger.info("下载失败!");
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			try {
				ftpClientPool.returnFtpClient(ftpClient);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		
	}
	
}

 

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值