ftp连接池客户端

package com.scenetec.isv.utils.ftp.core;

import com.scenetec.isv.utils.ftp.config.FtpClientProperties;import lombok.extern.slf4j.Slf4j;import org.apache.commons.net.ftp.FTPClient;import org.apache.commons.net.ftp.FTPReply;import org.apache.commons.pool2.BasePooledObjectFactory;import org.apache.commons.pool2.PooledObject;import org.apache.commons.pool2.impl.DefaultPooledObject;import org.springframework.stereotype.Component;

/** * @author [email protected] * @description ftpclient客户端连接工厂类 * @date 2018/12/19 */@Slf4j@Componentpublic class FtpClientFactory extends BasePooledObjectFactory<FTPClient> {

private FtpClientProperties config;

public FtpClientFactory(FtpClientProperties config) {      this.config = config;   }

@Override   public FTPClient create() {

FTPClient ftpClient = new FTPClient();      ftpClient.setControlEncoding(config.getEncoding());      if (config.getConnectTimeout() != null) {         ftpClient.setConnectTimeout(config.getConnectTimeout());      }

try {         ftpClient.connect(config.getHost(), config.getPort());         int replyCode = ftpClient.getReplyCode();         if (!FTPReply.isPositiveCompletion(replyCode)) {            ftpClient.disconnect();            log.warn("FTPServer refused connection,replyCode:{}", replyCode);            return null;         }

if (!ftpClient.login(config.getUsername(), config.getPassword())) {            log.warn("FTPClient login failed... username is {}; password: {}", config.getUsername(), config.getPassword());         }

ftpClient.setBufferSize(config.getBufferSize());         ftpClient.setFileType(config.getTransferFileType());         if (config.isPassiveMode()) {            ftpClient.enterLocalPassiveMode();         }

} catch (Exception ex) {         ex.printStackTrace();         log.error("Failed to create FTP connection");      }

return ftpClient;   }

void destroyObject(FTPClient client) {      destroyObject(wrap(client));   }

/**    * 用PooledObject封装对象放入池中    * @param ftpClient ftp客户端    * @return 默认池对象    */   @Override   public PooledObject<FTPClient> wrap(FTPClient ftpClient) {      return new DefaultPooledObject<>(ftpClient);   }

/**    * 销毁FtpClient对象    * @param ftpPooled ftp池对象    */   @Override   public void destroyObject(PooledObject<FTPClient> ftpPooled) {      if (ftpPooled == null) {         return;      }

FTPClient ftpClient = ftpPooled.getObject();

try {         if (ftpClient.isConnected()) {            ftpClient.logout();         }      } catch (Exception ex) {         ex.printStackTrace();         log.error("Failure to destroy FTP connection pool.");      } finally {         try {            ftpClient.disconnect();         } catch (Exception ex) {            ex.printStackTrace();            log.error("Failed to close FTP connection pool.");         }      }   }

/**    * 验证FtpClient对象    * @param ftpPooled ftp池对象    * @return 发送一个NOOP命令到FTP服务器,如果成功返回true,否则为false。    */   @Override   public boolean validateObject(PooledObject<FTPClient> ftpPooled) {      try {         FTPClient ftpClient = ftpPooled.getObject();         if (ftpClient == null) {            return false;         }         if (!ftpClient.isConnected()) {            return false;         }         return ftpClient.sendNoOp();      } catch (Exception ex) {         ex.printStackTrace();      }      return false;   }

}
package com.scenetec.isv.utils.ftp.core;

import lombok.extern.slf4j.Slf4j;import org.apache.commons.net.ftp.FTPClient;import org.apache.commons.pool2.BaseObjectPool;import org.springframework.util.ObjectUtils;

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

/** * @author [email protected] * @description ftp客户端连接池类 * @date 2018/12/19 */@Slf4j@Deprecatedpublic class FtpClientPool extends BaseObjectPool<FTPClient> {

private static final int DEFAULT_POOL_SIZE = 5;   private final BlockingQueue<FTPClient> pool;   private final FtpClientFactory factory;

/**    * 初始化连接池,需要注入一个工厂来提供FTPClient实例    * @param factory    */   public FtpClientPool(FtpClientFactory factory) {      this(DEFAULT_POOL_SIZE, factory);   }

public FtpClientPool(int poolSize, FtpClientFactory factory) {      this.factory = factory;      this.pool = new ArrayBlockingQueue<>(poolSize * 2);      initPool(poolSize);   }

/**    * 初始化连接池,需要注入一个工厂来提供FTPClient实例    * @param maxPoolSize    */   private void initPool(int maxPoolSize) {      try {         for (int i = 0; i < maxPoolSize; i++) {            addObject();         }      } catch (Exception ex) {         ex.printStackTrace();         throw new RuntimeException("Failed to initialize FTP thread pool.");      }   }

/**    * 客户端从池中借出一个对象    * @return    * @throws Exception    * @throws NoSuchElementException    * @throws IllegalStateException    */   @Override   public FTPClient borrowObject() throws Exception, NoSuchElementException, IllegalStateException {      FTPClient client = pool.take();      if (ObjectUtils.isEmpty(client)) {         // 创建新的连接         client = factory.create();         // 返换对象         returnObject(client);      }      // 验证对象是否有效      else if (!factory.validateObject(factory.wrap(client))) {         // 对无效的对象进行处理         invalidateObject(client);         // 创建新的对象         client = factory.create();         // 将新的对象放入连接池         returnObject(client);      }      // 返回ftp对象      return client;   }

/**    * 返还对象到连接池中    * @param client    * @throws Exception    */   @Override   public void returnObject(FTPClient client) {      try {         long timeout = 3L;         if (client != null) {            if (client.isConnected()) {               if (pool.size() < DEFAULT_POOL_SIZE) {                  if (!pool.offer(client, timeout, TimeUnit.SECONDS)) {                     factory.destroyObject(client);                  }               } else {                  factory.destroyObject(client);               }            } else {               factory.destroyObject(client);            }         }      } catch (Exception ex) {         ex.printStackTrace();         log.error("Failed to return FTP connection object.");      }   }

/**    * 移除无效的对象    * @param client    * @throws Exception    */   @Override   public void invalidateObject(FTPClient client) {      try {         // 移除无效对象         pool.remove(client);         // 注销对象         factory.destroyObject(client);      } catch (Exception ex) {         ex.printStackTrace();         log.error("Failed to remove invalid FTP object.");      }   }

/**    * 增加一个新的链接,超时失效    * @throws Exception    * @throws IllegalStateException    * @throws UnsupportedOperationException    */   @Override   public void addObject() throws Exception, IllegalStateException, UnsupportedOperationException {      pool.offer(factory.create(), 3, TimeUnit.SECONDS);   }

@Override   public void close() {      try {         while (pool.iterator().hasNext()) {            FTPClient client = pool.take();            factory.destroyObject(client);         }      } catch (Exception ex) {         ex.printStackTrace();         log.error("Failed to close FTP object.");      }   }}

package com.scenetec.isv.utils.ftp.core;

import lombok.extern.slf4j.Slf4j;import org.apache.commons.lang3.StringUtils;import org.apache.commons.net.ftp.FTPClient;import org.apache.commons.net.ftp.FTPReply;import org.apache.commons.pool2.impl.GenericObjectPool;import org.springframework.stereotype.Component;

import java.io.*;

/** * @author [email protected] * @description ftpClient模板上传下载文件类 * @date 2018/12/20 */@Slf4j@Componentpublic class FtpClientTemplate {

private GenericObjectPool<FTPClient> ftpClientPool;

public FtpClientTemplate(FtpClientFactory ftpClientFactory) {      this.ftpClientPool = new GenericObjectPool<>(ftpClientFactory);   }

/**    * 上传文件    *    * @param localPath 本地路径    * @param remotePath 远程路径,必须包含文件名("/"为当前ftp用户根路径)    * @return 上传成功返回true, 否则返回false    */   public boolean uploadFile(String localPath, String remotePath) {      if (StringUtils.isBlank(localPath)) {         log.error("本地文件路径为空");         return false;      }      return uploadFile(new File(localPath), remotePath);   }

/**    * 上传文件    *    * @param localFile 本地文件    * @param remotePath 远程文件,必须包含文件名    * @return 上传成功返回true, 否则返回false    */   public boolean uploadFile(File localFile, String remotePath) {      if (!localFile.exists()) {         log.error("本地文件不存在");         return false;      }      if (!localFile.isFile()) {         log.error("上传类型不是文件");      }      if (StringUtils.isBlank(remotePath)) {         remotePath = "/";      }      FileInputStream fis = null;      BufferedInputStream bis = null;      try {         fis = new FileInputStream(localFile);         bis = new BufferedInputStream(fis);         // 上传         return uploadFile(bis, remotePath);      } catch (FileNotFoundException fex) {         fex.printStackTrace();         log.error("系统找不到指定的文件:{}", localFile);      } catch (Exception ex) {         ex.printStackTrace();         log.error("上传文件异常。");      } finally {         try {            if (bis != null) {               bis.close();            }         } catch (Exception ex) {            ex.printStackTrace();         }         try {            if (fis != null) {               fis.close();            }         } catch (Exception ex) {            ex.printStackTrace();         }      }      return false;   }

/**    * 上传文件    *    * @param fileContent 文件内容    * @param remotePath 远程文件,必须包含文件名    * @return 上传成功返回true, 否则返回false    */   public boolean uploadFile(byte[] fileContent, String remotePath) {      if (fileContent == null || fileContent.length <= 0) {         log.error("上传文件内容为空。");         return false;      }      InputStream is = null;      try {         is = new ByteArrayInputStream(fileContent);         // 上传         return uploadFile(is, remotePath);      } catch (Exception ex) {         ex.printStackTrace();         log.error("上传文件异常。原因:【{}】", ex.getMessage());      } finally {         try {            if (is != null) {               is.close();            }         } catch (Exception ex) {            ex.printStackTrace();         }      }      return false;   }

/**    * 上传文件    *    * @param inputStream 文件流    * @param remotePath 远程文件,必须包含文件名    * @return 上传成功返回true, 否则返回false    */   public boolean uploadFile(InputStream inputStream, String remotePath) {      // 上传      FTPClient client = null;      try {         // 获取远程文件路径         String remoteFilePath = getRemoteFilePath(remotePath);         // 获取远程文件名         String remoteFileName = getRemoteFileName(remotePath);         // 从池中获取对象         client = getFtpClient();         // 验证连接是否成功         boolean bool = FTPReply.isPositiveCompletion(client.getReplyCode());         if (!bool) {            log.error("连接服务器失败,{}", client.getReplyString());            return false;         }         // 切换工作路径         bool = changeDirectory(client, remoteFilePath);         if (!bool) {            log.error("切换工作路径失败,{}", client.getReplyString());            return false;         }         // 设置重试次数         final int retryTime = 3;         boolean retryResult = false;

for (int i = 0; i <= retryTime; i++) {            boolean success = client.storeFile(remoteFileName, inputStream);            if (success) {               log.info("文件【{}】上传成功。", remotePath);               retryResult = true;               break;            } else {               log.error("文件上传失败。{}", client.getReplyString());            }            log.warn("文件【{}】上传失败,重试上传...尝试{}次", remotePath, i);         }

return retryResult;      } catch (Exception ex) {         ex.printStackTrace();         log.error("上传文件异常。");      } finally {         // 将对象放回池中         if (client != null) {            ftpClientPool.returnObject(client);         }      }

return false;   }

/**    * 下载文件    * @param remotePath 远程文件,必须包含文件名    * @param localPath 本地路径,必须包含文件名(全路径)    * @return 下载成功返回true,否则返回false    */   public boolean downloadFile(String remotePath, String localPath) {      if (StringUtils.isBlank(remotePath)) {         remotePath = "/";      }      if (StringUtils.isBlank(localPath)) {         log.error("本地文件路径为空");         return false;      }      // 创建本地文件路径      File localFile = new File(localPath);      if (!localFile.exists()) {         File parentFile = localFile.getParentFile();         if (!parentFile.exists()) {            boolean bool = parentFile.mkdirs();            if (!bool) {               log.error("创建本地路径失败");               return false;            }         }      }      // 下载      FTPClient client = null;      OutputStream os = null;      try {         os = new FileOutputStream(localPath);         // 获取远程文件路径         String remoteFilePath = getRemoteFilePath(remotePath);         // 获取远程文件名         String remoteFileName = getRemoteFileName(remotePath);         // 从池中获取对象         client = getFtpClient();         // 验证连接是否成功         boolean bool = FTPReply.isPositiveCompletion(client.getReplyCode());         if (!bool) {            log.error("连接服务器失败,{}", client.getReplyString());            return false;         }         // 切换工作路径         bool = client.changeWorkingDirectory(remoteFilePath);         if (!bool) {            log.error("切换工作路径失败,{}", client.getReplyString());            return false;         }         // 设置重试次数         final int retryTime = 3;         boolean retryResult = false;

for (int i = 0; i <= retryTime; i++) {            boolean success = client.retrieveFile(remoteFileName, os);            if (success) {               log.info("文件【{}】下载成功。", localPath);               retryResult = true;               break;            } else {               log.error("文件下载失败。 {}", client.getReplyString());            }            log.warn("文件【{}】下载失败,重试下载...尝试{}次", localPath, i);         }         // 返回结果         return retryResult;      } catch (Exception ex) {         ex.printStackTrace();         log.error("下载文件异常。");      } finally {         if (client != null) {            ftpClientPool.returnObject(client);         }         try {            if (os != null) {               os.close();            }         } catch (Exception ex) {            ex.printStackTrace();         }      }      return false;   }

/**    * 删除文件    * @param remotePath 远程文件,必须包含文件名    * @return 下载成功返回true,否则返回false    */   public boolean deleteFile(String remotePath) {      FTPClient client = null;      try {         // 从池中获取对象         client = getFtpClient();         // 验证连接是否成功         boolean bool = FTPReply.isPositiveCompletion(client.getReplyCode());         if (!bool) {            log.error("连接服务器失败,{}", client.getReplyString());            return false;         }         // 删除文件         bool = client.deleteFile(remotePath);         if (!bool) {            log.error("删除文件失败,{}", client.getReplyString());         }         return bool;      } catch (Exception ex) {         ex.printStackTrace();         log.error("删除文件异常。");      } finally {         if (client != null) {            ftpClientPool.returnObject(client);         }      }      return false;   }

/**    * 获取远程工作目录    * @param remotePath 远程路径    * @return 返回工作路径    */   private String getRemoteFilePath(String remotePath) {      if (StringUtils.isNotBlank(remotePath)) {         return remotePath.substring(0, remotePath.lastIndexOf("/") + 1);      }      return "/";   }

/**    * 获取远程文件名    * @param remotePath 远程路径    * @return 返回文件名    */   private String getRemoteFileName(String remotePath) {      if (StringUtils.isNotBlank(remotePath)) {         return remotePath.substring(remotePath.lastIndexOf("/") + 1);      }      return "";   }

/**    * 验证连接是否成功    * @return 连接登录成功返回true,否则返回false    */   private FTPClient getFtpClient () {      FTPClient client = null;      try {         while (true) {            // 获取客户端            client = ftpClientPool.borrowObject();            // 验证客户端            if (client == null) {               continue;            } else {               if (!client.isConnected() || !FTPReply.isPositiveCompletion(client.getReplyCode())) {                  ftpClientPool.invalidateObject(client);               } else {                  break;               }            }         }      } catch (Exception ex) {         ex.printStackTrace();      }      return client;   }

/**    * 切换工作目录    * @param client ftp客户端    * @param dir 工作目录    * @return 切换成功返回true,否则返回false    */   private boolean changeDirectory(FTPClient client, String dir) {      try {         if (client == null || StringUtils.isBlank(dir)) {            return false;         }

String fileBackslashSeparator = "\\";         String fileSeparator = "/";

if (StringUtils.contains(dir, fileBackslashSeparator)) {            dir = StringUtils.replaceAll(dir, fileBackslashSeparator, fileSeparator);         }

String[] dirArray = StringUtils.split(dir, fileSeparator);

String tmp = "";         for (String aDirArray : dirArray) {            tmp += fileSeparator + aDirArray;            if (!client.changeWorkingDirectory(tmp)) {               // 创建工作目录               client.makeDirectory(tmp);               // 切换工作目录               client.changeWorkingDirectory(tmp);            }         }         return true;      } catch (Exception ex) {         ex.printStackTrace();         log.error("切换工作目录失败。");      }      return false;   }

}

原文地址:https://www.cnblogs.com/sxpdy8571/p/10263847.html

时间: 2024-10-09 23:26:53

ftp连接池客户端的相关文章

JAVA ftp连接池功能实现

抽象类: package com.echo.store; import java.util.Enumeration; import java.util.Hashtable; abstract class ObjectPool<T> { long ttl ; Hashtable<T,Long> lock,unlock ; public ObjectPool() { ttl = 50000; lock = new Hashtable<T, Long>(); unlock =

支持并发的http客户端(基于tcp连接池以及netty)

闲来无事,将以前自己写的一个库放出来吧.. 有的时候会有这样子的需求: (1)服务器A通过HTTP协议来访问服务器B (2)服务器A可能会并发的像B发送很多HTTP请求 类似于上述的需求,可能并不常见...因为在业务中确实遇到了这样子的场景,所以就自己动手开发了一个库... 实现原理: (1)底层IO通过netty搞 (2)维护一个tcp的长连接池,这样子就不用每次发送请求还要建立一个tcp连接了... 下面直接来看怎么用吧: (1)最常规的用法,向www.baidu.com发送100次get请

[学习积累]memcached客户端和连接池

前阵子在网上找了个demo学了一下memcached的简单使用. 今天回顾了一下,我想:连接池不是应该算是服务端管理的东西么,Client应该是客户端管理的东西,怎么能放在同一个class里边呢?于是把demo改了改,代码如下: 服务端: package studyMemcached; import com.danga.MemCached.SockIOPool; public class MemServer {     private static SockIOPool pool;     pu

oracle database resident connection pooling(驻留连接池)

oracle在11g中引入了database resident connection pooling(DRCP).在此之前,我们可以使用dedicated 或者share 方式来链接数据库,dedicated方式是oracle数据库默认的链接方式,无需过多的配置,而且关于dedicated的bug也是非常少的,因此,通常情况下,建议使用dedicated方式来链接数据库.但是,在服务器资源有限,并且同时连接数据库的用户量非常大时,dedicated方式就无能为力了.假设并发用户为5000,每个d

JBoss配置连接池

什么是数据库连接池? 配置连接池为的是解决效率问题.因为每创建一个连接都是很耗时的,有了连接池,就可以提前放一些连接进去.以后我们再用连接就去连接池里面取而不是每次都创建.但是我们知道连接池是有上限的,如果只允许我们放10个,那么当这10个连接都被占用的时候,下一个用户再来请求连接将不能得到,只好等待,如果等的时间太长了就会抛出timeout的异常.使用完连接后要释放,否则会一直占着资源,当连接全部被占用而得不到释放时,就会出现错误... JBoss实现了J2EE的13个规范包括JNDI,JND

Spring c3p0连接池配置

数据库连接池数据库连接池的基本思想就是为数据库连接建立一个"缓冲池".预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需从"缓冲池"中取出一个,使用完毕之后再放回去.我们可以通过设定连接池最大连接数来防止系统无尽的与数据库连接. 获取一个连接,系统要在背后做很多消耗资源的事情,大多时候,创建连接的时间比执行sql语句的时间还要长.用户每次请求都需要向数据库获得链接,而数据库创建连接通常需要消耗相对较大的资源,创建时间也较长. 数据库连接池负责分配,管理和

搭建spring工程配置数据源连接池

Spring作为一个优秀的开源框架,越来越为大家所熟知,前段时间用搭了个spring工程来管理数据库连接池,没有借助Eclipse纯手工搭建,网上此类文章不多,这里给大家分享一下,也作为一个手记. 工程结构: 注意:src目录下的applicationContext.xml是单元测试用的,作为web工程的话就使用WEB-INF下的applicationContext.xml. 1.下载jar包 这里需要下载很多spring的jar包,推荐去官网下载,很多人会说官网只提供maven和gradle下

python之模块ftplib(FTP协议的客户端)

# -*- coding: utf-8 -*- #python 27 #xiaodeng #python之模块ftplib(FTP协议的客户端) #需求:快速进行ftp上传 ,下载,查询文件 from ftplib import FTP ftp = FTP() #设置变量 timeout = 30 port = 21 ftp.connect('192.168.1.188',port,timeout) # 连接FTP服务器 ftp.login('UserName','888888') # 登录 p

DBCP、C3P0、Proxool 、 BoneCP开源连接池的比较

 简介   使用评价  项目主页  DBCP DBCP是一个依赖Jakarta commons-pool对象池机制的数据库连接池.DBCP可以直接的在应用程序用使用 可以设置最大和最小连接,连接等待时间等,基本功能都有,此连接池的持续运行的稳定性还是可以,不过速度稍慢,在大并发量的压力下稳定性有所下降,此外不提供连接池监控 http://homepages.nildram. co.uk/~slink/java/DBPool/  C3P0  C3P0是一个开放源代码的JDBC连接池,它在lib目录