# ftp-starter
**Repository Path**: Instinctb/ftp-starter
## Basic Information
- **Project Name**: ftp-starter
- **Description**: No description available
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2026-04-17
- **Last Updated**: 2026-04-17
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# Ftp连接池-springboot-starter
## 1.背景:
项目开发过程中,经常使用的ftp的工具类,为了减少ftp的创建连接和关闭连接,需要一个类似数据库连接池的ftp连接池
## 2.项目依赖:
```
commons-net
commons-net
org.apache.commons
commons-pool2
```
2.2 pool2的组成
- PooledObject(池化对象)
- PooledObjectFactory(对象工厂)
- ObjectPool (对象池)
对应为:
- FTPClient(池化对象)
- FTPClientFactory(对象工厂)
- FTPClientPool(对象池)
-

## 3.FTP配置类
```
@Data
@Component
@PropertySource("classpath:ftp.properties")
@ConfigurationProperties(prefix = "ftp")
public class FtpConfigOptions extends GenericObjectPoolConfig {
/**
* 地址
*/
private String host;
/**
* 端口号
*/
private int port=21;
/**
* 用户名
*/
private String username;
/**
* Miami
*/
private String password;
/**
* 方式
*/
private int passiveMode = FTP.BINARY_FILE_TYPE;
/**
* 编码方式
*/
private String encoding="UTF-8";
/**
* 超时时间
*/
private int clientTimeout=120000;
/**
* 缓冲区
*/
private int bufferSize =1024;
```
## 4.FTP连接工厂
在commons-pool2中有两种工厂:PooledObjectFactory 和KeyedPooledObjectFactory,我们使用前者
```
public interface PooledObjectFactory {
//创建对象
PooledObject makeObject();
//激活对象
void activateObject(PooledObject obj);
//钝化对象
void passivateObject(PooledObject obj);
//验证对象
boolean validateObject(PooledObject obj);
//销毁对象
void destroyObject(PooledObject obj);
}
```
```
@Slf4j
public class FtpClientFactory implements PooledObjectFactory {
private FtpConfigOptions ftpProperties;
public FtpClientFactory(FtpConfigOptions ftpProperties) {
this.ftpProperties = ftpProperties;
}
/**
* 创建client端
* @return
* @throws Exception
*/
@Override
public PooledObject makeObject() throws Exception {
FTPClient ftpClient = new FTPClient();
ftpClient.setControlEncoding(ftpProperties.getEncoding());
ftpClient.setConnectTimeout(ftpProperties.getClientTimeout());
try {
ftpClient.connect(ftpProperties.getHost(), ftpProperties.getPort());
int reply = ftpClient.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
ftpClient.disconnect();
log.warn("FTPServer refused connection");
return null;
}
boolean result = ftpClient.login(ftpProperties.getUsername(), ftpProperties.getPassword());
ftpClient.setFileType(ftpProperties.getPassiveMode());
if (!result) {
log.warn("ftpClient login failed... username is {}", ftpProperties.getUsername());
}
} catch (Exception e) {
log.error("create ftp connection failed...{}", e);
throw e;
}
return wrap(ftpClient);
}
/**
* 包装成PooledObject
* @param ftpClient
* @return
*/
public PooledObject wrap(FTPClient ftpClient) {
return new DefaultPooledObject(ftpClient);
}
/**
* 销毁对象
*
* @param pooledObject
* @throws Exception
*/
@Override
public void destroyObject(PooledObject pooledObject) throws Exception {
try {
if(pooledObject.getObject() != null && pooledObject.getObject().isConnected()) {
pooledObject.getObject().logout();
}
} catch (Exception e) {
log.error("ftp client logout failed...{}", e);
throw e;
} finally {
if(pooledObject.getObject() != null) {
pooledObject.getObject().disconnect();
}
}
}
/**
* a验证对象是否正确
* @param pooledObject
* @return
*/
@Override
public boolean validateObject(PooledObject pooledObject) {
try {
pooledObject.getObject().sendNoOp();
} catch (Exception e) {
log.error("Failed to validate client: {}");
}
return false;
}
@Override
public void activateObject(PooledObject pooledObject) throws Exception {
}
@Override
public void passivateObject(PooledObject pooledObject) throws Exception {
}
```
## 5.FTP连接池
```
public class FtpClientPool extends GenericObjectPool {
private FtpClientFactory ftpClientFactory;
private FtpConfigOptions ftpConfigOptions;
public FtpClientPool(FtpClientFactory ftpClientFactory,FtpConfigOptions ftpConfigOptions) {
super(ftpClientFactory,ftpConfigOptions);
this.ftpClientFactory=ftpClientFactory;
this.ftpConfigOptions=ftpConfigOptions;
}
```
## 6.FTP工具类
```
public class FtpUtils {
/**
* FTP的连接池
*/
public static FtpClientPool ftpClientPool;
/**
* FTPClient对象
*/
public static FTPClient ftpClient;
//@Autowired static方式可以采用setter方法
public FtpUtils(FtpClientPool ftpClientPool) {
FtpUtils.ftpClientPool= ftpClientPool;
}
//private static FtpUtils ftpUtils;
/* *//**
* 初始化设置
* @return
*//*
@PostConstruct
public boolean init() {
ftpUtils = this;
return true;
}*/
/**
* 获取连接对象
* @return
* @throws Exception
*/
public static FTPClient getFTPClient() throws Exception {
//初始化的时候从队列中取出一个连接
synchronized (ftpClientPool) {
ftpClient = ftpClientPool.borrowObject();
}
return ftpClient;
}
/**
* 当前命令执行完成命令完成
* @throws IOException
*/
public void complete() throws IOException {
ftpClient.completePendingCommand();
}
/**
* 当前线程任务处理完成,加入到队列的最后
* @return
*/
public void disconnect() throws Exception {
ftpClientPool.returnObject(ftpClient);
}
/**
* Description: 向FTP服务器上传文件
*
* @Version1.0
* @param remoteFile
* 上传到FTP服务器上的文件名
* @param input
* 本地文件流
* @return 成功返回true,否则返回false
*/
public static boolean uploadFile(String remoteFile, InputStream input) {
boolean result = false;
try {
getFTPClient();
ftpClient.enterLocalPassiveMode();
result = ftpClient.storeFile(remoteFile, input);
input.close();
ftpClient.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* Description: 向FTP服务器上传文件
*
* @Version1.0
* @param remoteFile
* 上传到FTP服务器上的文件名
* @param localFile
* 本地文件
* @return 成功返回true,否则返回false
*/
public static boolean uploadFile(String remoteFile, String localFile){
FileInputStream input = null;
try {
input = new FileInputStream(new File(localFile));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return uploadFile(remoteFile, input);
}
/**
* 拷贝文件
* @param fromFile
* @param toFile
* @return
* @throws Exception
*/
public boolean copyFile(String fromFile, String toFile) throws Exception {
InputStream in=getFileInputStream(fromFile);
getFTPClient();
boolean flag = ftpClient.storeFile(toFile, in);
in.close();
return flag;
}
/**
* 获取文件输入流
* @param fileName
* @return
* @throws IOException
*/
public static InputStream getFileInputStream(String fileName) throws Exception {
ByteArrayOutputStream fos=new ByteArrayOutputStream();
getFTPClient();
ftpClient.retrieveFile(fileName, fos);
ByteArrayInputStream in=new ByteArrayInputStream(fos.toByteArray());
fos.close();
return in;
}
/**
* Description: 从FTP服务器下载文件
*
* @Version1.0
* @return
*/
public static boolean downFile(String remoteFile, String localFile){
boolean result = false;
try {
getFTPClient();
OutputStream os = new FileOutputStream(localFile);
ftpClient.retrieveFile(remoteFile, os);
ftpClient.logout();
ftpClient.disconnect();
result = true;
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
} catch (Exception e) {
e.printStackTrace();
}
}
return result;
}
/**
* 从ftp中获取文件流
* @param filePath
* @return
* @throws Exception
*/
public static InputStream getInputStream(String filePath) throws Exception {
getFTPClient();
InputStream inputStream = ftpClient.retrieveFileStream(filePath);
return inputStream;
}
/**
* ftp中文件重命名
* @param fromFile
* @param toFile
* @return
* @throws Exception
*/
public boolean rename(String fromFile,String toFile) throws Exception {
getFTPClient();
boolean result = ftpClient.rename(fromFile,toFile);
return result;
}
/**
* 获取ftp目录下的所有文件
* @param dir
* @return
*/
public FTPFile[] getFiles(String dir) throws Exception {
getFTPClient();
FTPFile[] files = new FTPFile[0];
try {
files = ftpClient.listFiles(dir);
}catch (Throwable thr){
thr.printStackTrace();
}
return files;
}
/**
* 获取ftp目录下的某种类型的文件
* @param dir
* @param filter
* @return
*/
public FTPFile[] getFiles(String dir, FTPFileFilter filter) throws Exception {
getFTPClient();
FTPFile[] files = new FTPFile[0];
try {
files = ftpClient.listFiles(dir, filter);
}catch (Throwable thr){
thr.printStackTrace();
}
return files;
}
/**
* 创建文件夹
* @param remoteDir
* @return 如果已经有这个文件夹返回false
*/
public boolean makeDirectory(String remoteDir) throws Exception {
getFTPClient();
boolean result = false;
try {
result = ftpClient.makeDirectory(remoteDir);
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
public boolean mkdirs(String dir) throws Exception {
boolean result = false;
if (null == dir) {
return result;
}
getFTPClient();
ftpClient.changeWorkingDirectory("/");
StringTokenizer dirs = new StringTokenizer(dir, "/");
String temp = null;
while (dirs.hasMoreElements()) {
temp = dirs.nextElement().toString();
//创建目录
ftpClient.makeDirectory(temp);
//进入目录
ftpClient.changeWorkingDirectory(temp);
result = true;
}
ftpClient.changeWorkingDirectory("/");
return result;
}
```
## 7.使用
## 8.参考资料
https://www.jianshu.com/p/292d376179b1?utm_source=oschina-app