ftp连接池客户端

1、添加ftp配置

 1 package com.scenetec.isv.utils.ftp.config;
 2 
 3 import lombok.Getter;
 4 import lombok.Setter;
 5 import org.apache.commons.net.ftp.FTP;
 6 import org.springframework.boot.context.properties.ConfigurationProperties;
 7 import org.springframework.stereotype.Component;
 8 
 9 /**
10  * @author shendunyuan@scenetec.com
11  * @date 2018/12/19
12  */
13 @Getter
14 @Setter
15 @Component
16 @ConfigurationProperties(ignoreUnknownFields = false, prefix = "ftp.client")
17 public class FtpClientProperties {
18 
19     /**
20      * ftp地址
21      */
22     private String host;
23 
24     /**
25      * 端口号
26      */
27     private Integer port = 21;
28 
29     /**
30      * 登录用户
31      */
32     private String username;
33 
34     /**
35      * 登录密码
36      */
37     private String password;
38 
39     /**
40      * 被动模式
41      */
42     private boolean passiveMode = false;
43 
44     /**
45      * 编码
46      */
47     private String encoding = "UTF-8";
48 
49     /**
50      * 连接超时时间(秒)
51      */
52     private Integer connectTimeout;
53 
54     /**
55      * 缓冲大小
56      */
57     private Integer bufferSize = 1024;
58 
59     /**
60      * 设置keepAlive
61      * 单位:秒  0禁用
62      */
63     private Integer keepAliveTimeout = 0;
64 
65     /**
66      * 传输文件类型
67      */
68     private Integer transferFileType = FTP.BINARY_FILE_TYPE;
69 
70 }
View Code
1 ftp:
2  client:
3     host: 132.232.68.30
4     port: 21
5     username: isv
6     password: xintai1234
7     passiveMode: true
View Code

2、ftp客户端工厂处理类

  1 package com.scenetec.isv.utils.ftp.core;
  2 
  3 import com.scenetec.isv.utils.ftp.config.FtpClientProperties;
  4 import lombok.extern.slf4j.Slf4j;
  5 import org.apache.commons.net.ftp.FTPClient;
  6 import org.apache.commons.net.ftp.FTPReply;
  7 import org.apache.commons.pool2.BasePooledObjectFactory;
  8 import org.apache.commons.pool2.PooledObject;
  9 import org.apache.commons.pool2.impl.DefaultPooledObject;
 10 import org.springframework.stereotype.Component;
 11 
 12 /**
 13  * @author shendunyuan@scenetec.com
 14  * @date 2018/12/19
 15  */
 16 @Slf4j
 17 @Component
 18 public class FtpClientFactory extends BasePooledObjectFactory<FTPClient> {
 19 
 20     private FtpClientProperties config;
 21 
 22     public FtpClientFactory(FtpClientProperties config) {
 23         this.config = config;
 24     }
 25 
 26     @Override
 27     public FTPClient create() {
 28 
 29         FTPClient ftpClient = new FTPClient();
 30         ftpClient.setControlEncoding(config.getEncoding());
 31         if (null != config.getConnectTimeout()) {
 32             ftpClient.setConnectTimeout(config.getConnectTimeout());
 33         }
 34 
 35         try {
 36             ftpClient.connect(config.getHost(), config.getPort());
 37             int replyCode = ftpClient.getReplyCode();
 38             if (!FTPReply.isPositiveCompletion(replyCode)) {
 39                 ftpClient.disconnect();
 40                 log.warn("FTPServer refused connection,replyCode:{}", replyCode);
 41                 return null;
 42             }
 43 
 44             if (!ftpClient.login(config.getUsername(), config.getPassword())) {
 45                 log.warn("FTPClient login failed... username is {}; password: {}", config.getUsername(), config.getPassword());
 46             }
 47 
 48             ftpClient.setBufferSize(config.getBufferSize());
 49             ftpClient.setFileType(config.getTransferFileType());
 50             if (config.isPassiveMode()) {
 51                 ftpClient.enterLocalPassiveMode();
 52             }
 53 
 54         } catch (Exception ex) {
 55             ex.printStackTrace();
 56             log.error("Failed to create FTP connection");
 57         }
 58 
 59         return ftpClient;
 60     }
 61 
 62     void destroyObject(FTPClient client) {
 63         destroyObject(wrap(client));
 64     }
 65 
 66     /**
 67      * 用PooledObject封装对象放入池中
 68      * @param ftpClient ftp客户端
 69      * @return 默认池对象
 70      */
 71     @Override
 72     public PooledObject<FTPClient> wrap(FTPClient ftpClient) {
 73         return new DefaultPooledObject<>(ftpClient);
 74     }
 75 
 76     /**
 77      * 销毁FtpClient对象
 78      * @param ftpPooled ftp池对象
 79      */
 80     @Override
 81     public void destroyObject(PooledObject<FTPClient> ftpPooled) {
 82         if (ftpPooled == null) {
 83             return;
 84         }
 85 
 86         FTPClient ftpClient = ftpPooled.getObject();
 87 
 88         close(ftpClient);
 89     }
 90 
 91     /**
 92      * 销毁FtpClient对象
 93      * @param client ftp对象
 94      */
 95     public void close(FTPClient client) {
 96         try {
 97             if (client.isConnected()) {
 98                 client.logout();
 99             }
100         } catch (Exception ex) {
101             ex.printStackTrace();
102             log.error("Failure to destroy FTP connection pool.");
103         } finally {
104             try {
105                 client.disconnect();
106             } catch (Exception ex) {
107                 ex.printStackTrace();
108                 log.error("Failed to close FTP connection pool.");
109             }
110         }
111     }
112 
113     /**
114      * 验证FtpClient对象
115      * @param ftpPooled ftp池对象
116      * @return 发送一个NOOP命令到FTP服务器,如果成功返回true,否则为false。
117      */
118     @Override
119     public boolean validateObject(PooledObject<FTPClient> ftpPooled) {
120         try {
121             FTPClient ftpClient = ftpPooled.getObject();
122             if (ftpClient == null) {
123                 return false;
124             }
125             if (!ftpClient.isConnected()) {
126                 return false;
127             }
128             return ftpClient.sendNoOp();
129         } catch (Exception ex) {
130             ex.printStackTrace();
131         }
132         return false;
133     }
134 
135 }
View Code

3、ftp资源池处理类

  1 package com.scenetec.isv.utils.ftp.core;
  2 
  3 import lombok.extern.slf4j.Slf4j;
  4 import org.apache.commons.net.ftp.FTPClient;
  5 import org.apache.commons.pool2.BaseObjectPool;
  6 import org.springframework.util.ObjectUtils;
  7 
  8 import java.util.NoSuchElementException;
  9 import java.util.concurrent.ArrayBlockingQueue;
 10 import java.util.concurrent.BlockingQueue;
 11 import java.util.concurrent.TimeUnit;
 12 
 13 /**
 14  * @author shendunyuan@scenetec.com
 15  * @date 2018/12/19
 16  */
 17 @Slf4j
 18 public class FtpClientPool extends BaseObjectPool<FTPClient> {
 19 
 20     private static final int DEFAULT_POOL_SIZE = 5;
 21     private final BlockingQueue<FTPClient> pool;
 22     private final FtpClientFactory factory;
 23 
 24 
 25     /**
 26      * 初始化连接池,需要注入一个工厂来提供FTPClient实例
 27      * @param factory
 28      */
 29     public FtpClientPool(FtpClientFactory factory) {
 30         this(DEFAULT_POOL_SIZE, factory);
 31     }
 32 
 33     public FtpClientPool(int poolSize, FtpClientFactory factory) {
 34         this.factory = factory;
 35         this.pool = new ArrayBlockingQueue<>(poolSize * 2);
 36         initPool(poolSize);
 37     }
 38 
 39     /**
 40      * 初始化连接池,需要注入一个工厂来提供FTPClient实例
 41      * @param maxPoolSize
 42      */
 43     private void initPool(int maxPoolSize) {
 44         try {
 45             for (int i = 0; i < maxPoolSize; i++) {
 46                 addObject();
 47             }
 48         } catch (Exception ex) {
 49             ex.printStackTrace();
 50             throw new RuntimeException("Failed to initialize FTP thread pool.");
 51         }
 52     }
 53 
 54     /**
 55      * 客户端从池中借出一个对象
 56      * @return
 57      * @throws Exception
 58      * @throws NoSuchElementException
 59      * @throws IllegalStateException
 60      */
 61     @Override
 62     public FTPClient borrowObject() throws Exception, NoSuchElementException, IllegalStateException {
 63         FTPClient client = pool.take();
 64         if (ObjectUtils.isEmpty(client)) {
 65             // 创建新的连接
 66             client = factory.create();
 67         }
 68         // 验证对象是否有效
 69         else if (!factory.validateObject(factory.wrap(client))) {
 70             // 对无效的对象进行处理
 71             invalidateObject(client);
 72             // 创建新的对象
 73             client = factory.create();
 74         }
 75         // 返回ftp对象
 76         return client;
 77     }
 78 
 79     /**
 80      * 返还对象到连接池中
 81      * @param client
 82      * @throws Exception
 83      */
 84     @Override
 85     public void returnObject(FTPClient client) {
 86         try {
 87             long timeout = 3L;
 88             if (client != null) {
 89                 if (client.isConnected()) {
 90                     if (pool.size() < DEFAULT_POOL_SIZE) {
 91                         // 添加回队列
 92                         if (!pool.offer(client, timeout, TimeUnit.SECONDS)) {
 93                             factory.destroyObject(client);
 94                         }
 95                     } else {
 96                         factory.destroyObject(client);
 97                     }
 98                 } else {
 99                     factory.destroyObject(client);
100                 }
101             }
102         } catch (Exception ex) {
103             ex.printStackTrace();
104             log.error("Failed to return FTP connection object.");
105         }
106     }
107 
108     /**
109      * 移除无效的对象
110      * @param client
111      * @throws Exception
112      */
113     @Override
114     public void invalidateObject(FTPClient client) {
115         try {
116             // 移除无效对象
117             pool.remove(client);
118             // 注销对象
119             factory.destroyObject(client);
120         } catch (Exception ex) {
121             ex.printStackTrace();
122             log.error("Failed to remove invalid FTP object.");
123         }
124     }
125 
126     /**
127      * 增加一个新的链接,超时失效
128      * @throws Exception
129      * @throws IllegalStateException
130      * @throws UnsupportedOperationException
131      */
132     @Override
133     public void addObject() throws Exception, IllegalStateException, UnsupportedOperationException {
134         pool.offer(factory.create(), 3, TimeUnit.SECONDS);
135     }
136 
137     @Override
138     public void close() {
139         try {
140             while (pool.iterator().hasNext()) {
141                 FTPClient client = pool.take();
142                 factory.destroyObject(client);
143             }
144         } catch (Exception ex) {
145             ex.printStackTrace();
146             log.error("Failed to close FTP object.");
147         }
148     }
149 }
View Code

4、ftp上传下载基础处理类

  1 package com.scenetec.isv.utils.ftp.template;
  2 
  3 import lombok.extern.slf4j.Slf4j;
  4 import org.apache.commons.lang3.StringUtils;
  5 import org.apache.commons.net.ftp.FTPClient;
  6 
  7 import java.io.*;
  8 
  9 /**
 10  * @author shendunyuan@scenetec.com
 11  * @date 2019/1/22
 12  */
 13 @Slf4j
 14 public abstract class FtpBaseTemplate {
 15 
 16     /**
 17      * 上传文件
 18      *
 19      * @param localPath 本地路径
 20      * @param remotePath 远程路径,必须包含文件名("/"为当前ftp用户根路径)
 21      * @return 上传成功返回true, 否则返回false
 22      */
 23     public boolean uploadFile(String localPath, String remotePath) {
 24         if (StringUtils.isBlank(localPath)) {
 25             log.error("本地文件路径为空");
 26             return false;
 27         }
 28         return uploadFile(new File(localPath), remotePath);
 29     }
 30 
 31     /**
 32      * 上传文件
 33      *
 34      * @param localFile 本地文件
 35      * @param remotePath 远程文件,必须包含文件名
 36      * @return 上传成功返回true, 否则返回false
 37      */
 38     public boolean uploadFile(File localFile, String remotePath) {
 39         if (!localFile.exists()) {
 40             log.error("本地文件不存在");
 41             return false;
 42         }
 43         if (!localFile.isFile()) {
 44             log.error("上传类型不是文件");
 45         }
 46         if (StringUtils.isBlank(remotePath)) {
 47             remotePath = "/";
 48         }
 49         FileInputStream fis = null;
 50         BufferedInputStream bis = null;
 51         try {
 52             fis = new FileInputStream(localFile);
 53             bis = new BufferedInputStream(fis);
 54             // 上传
 55             return uploadFile(bis, remotePath);
 56         } catch (FileNotFoundException fex) {
 57             fex.printStackTrace();
 58             log.error("系统找不到指定的文件:{}", localFile);
 59         } catch (Exception ex) {
 60             ex.printStackTrace();
 61             log.error("上传文件异常。");
 62         } finally {
 63             try {
 64                 if (bis != null) {
 65                     bis.close();
 66                 }
 67             } catch (Exception ex) {
 68                 ex.printStackTrace();
 69             }
 70             try {
 71                 if (fis != null) {
 72                     fis.close();
 73                 }
 74             } catch (Exception ex) {
 75                 ex.printStackTrace();
 76             }
 77         }
 78         return false;
 79     }
 80 
 81     /**
 82      * 上传文件
 83      *
 84      * @param fileContent 文件内容
 85      * @param remotePath 远程文件,必须包含文件名
 86      * @return 上传成功返回true, 否则返回false
 87      */
 88     public boolean uploadFile(byte[] fileContent, String remotePath) {
 89         if (fileContent == null || fileContent.length <= 0) {
 90             log.error("上传文件内容为空。");
 91             return false;
 92         }
 93         InputStream is = null;
 94         try {
 95             is = new ByteArrayInputStream(fileContent);
 96             // 上传
 97             return uploadFile(is, remotePath);
 98         } catch (Exception ex) {
 99             ex.printStackTrace();
100             log.error("上传文件异常。原因:【{}】", ex.getMessage());
101         } finally {
102             try {
103                 if (is != null) {
104                     is.close();
105                 }
106             } catch (Exception ex) {
107                 ex.printStackTrace();
108             }
109         }
110         return false;
111     }
112 
113     /**
114      * 下载文件
115      * @param remotePath 远程文件,必须包含文件名
116      * @param localPath 本地路径,必须包含文件名(全路径)
117      * @return 下载成功返回true,否则返回false
118      */
119     public boolean downloadFile(String remotePath, String localPath) {
120         if (StringUtils.isBlank(remotePath)) {
121             remotePath = "/";
122         }
123         if (StringUtils.isBlank(localPath)) {
124             log.error("本地文件路径为空");
125             return false;
126         }
127         return downloadFile(new File(localPath), remotePath);
128     }
129 
130     /**
131      * 下载文件
132      * @param remotePath 远程文件,必须包含文件名
133      * @param localFile 本地文件
134      * @return 下载成功返回true,否则返回false
135      */
136     public boolean downloadFile(File localFile, String remotePath) {
137         // 创建本地文件路径
138         if (!localFile.exists()) {
139             File parentFile = localFile.getParentFile();
140             if (!parentFile.exists()) {
141                 boolean bool = parentFile.mkdirs();
142                 if (!bool) {
143                     log.error("创建本地路径失败");
144                     return false;
145                 }
146             }
147         }
148         OutputStream os = null;
149         try {
150             os = new FileOutputStream(localFile);
151             // 下载
152             return downloadFile(remotePath, os);
153         } catch (Exception ex) {
154             ex.printStackTrace();
155             log.error("下载文件异常。原因:【{}】", ex.getMessage());
156         } finally {
157             try {
158                 if (os != null) {
159                     os.close();
160                 }
161             } catch (Exception ex) {
162                 ex.printStackTrace();
163             }
164         }
165         return false;
166     }
167 
168     /**
169      * 删除文件
170      * @param remotePath 远程文件,必须包含文件名
171      * @return 删除成功返回true,否则返回false
172      */
173     public boolean deleteFile(String remotePath) {
174         if (StringUtils.isBlank(remotePath)) {
175             log.info("远程路径为空");
176             return false;
177         }
178         return deleFile(remotePath);
179     }
180 
181     /**
182      * 上传文件
183      * @param inputStream 文件流
184      * @param remotePath 远程路径,必须包含文件名
185      * @return 上传成功返回true,否则返回false
186      */
187     protected abstract boolean uploadFile(InputStream inputStream, String remotePath);
188     /**
189      * 下载文件
190      * @param remotePath 远程文件,必须包含文件名
191      * @param outputStream 本地文件流
192      * @return 下载成功返回true,否则返回false
193      */
194     protected abstract boolean downloadFile(String remotePath, OutputStream outputStream);
195     /**
196      * 删除文件
197      * @param remotePath 程文件,必须包含文件名
198      * @return 删除成功返回true,否则返回false
199      */
200     protected abstract boolean deleFile(String remotePath);
201 
202     /**
203      * 上传文件
204      *
205      * @param client ftp客户端
206      * @param inputStream 文件流
207      * @param remotePath 远程文件,必须包含文件名
208      * @return 上传成功返回true, 否则返回false
209      */
210     protected boolean uploadHandle(FTPClient client, InputStream inputStream, String remotePath) {
211         // 上传
212         try {
213             // 获取远程文件路径
214             String remoteFilePath = getRemoteFilePath(remotePath);
215             // 获取远程文件名
216             String remoteFileName = getRemoteFileName(remotePath);
217             // 切换工作路径
218             boolean bool = changeDirectory(client, remoteFilePath);
219             if (!bool) {
220                 log.error("切换工作路径失败,{}", client.getReplyString());
221                 return false;
222             }
223             // 设置重试次数
224             final int retryTime = 3;
225             boolean retryResult = false;
226 
227             for (int i = 0; i <= retryTime; i++) {
228                 boolean success = client.storeFile(remoteFileName, inputStream);
229                 if (success) {
230                     log.info("文件【{}】上传成功。", remotePath);
231                     retryResult = true;
232                     break;
233                 } else {
234                     log.error("文件上传失败。{}", client.getReplyString());
235                 }
236                 log.warn("文件【{}】上传失败,重试上传...尝试{}次", remotePath, i);
237             }
238 
239             return retryResult;
240         } catch (Exception ex) {
241             ex.printStackTrace();
242             log.error("上传文件异常。");
243         }
244 
245         return false;
246     }
247 
248     /**
249      * 下载文件
250      * @param client ftp客户端
251      * @param remotePath 远程文件,必须包含文件名
252      * @param outputStream 本地文件流
253      * @return 下载成功返回true,否则返回false
254      */
255     protected boolean downloadHandle(FTPClient client, String remotePath, OutputStream outputStream) {
256         // 下载
257         try {
258             // 获取远程文件路径
259             String remoteFilePath = getRemoteFilePath(remotePath);
260             // 获取远程文件名
261             String remoteFileName = getRemoteFileName(remotePath);
262             // 切换工作路径
263             boolean bool = client.changeWorkingDirectory(remoteFilePath);
264             if (!bool) {
265                 log.error("切换工作路径失败,{}", client.getReplyString());
266                 return false;
267             }
268             // 设置重试次数
269             final int retryTime = 3;
270             boolean retryResult = false;
271 
272             for (int i = 0; i <= retryTime; i++) {
273                 boolean success = client.retrieveFile(remoteFileName, outputStream);
274                 if (success) {
275                     log.info("文件【{}】下载成功。", remotePath);
276                     retryResult = true;
277                     break;
278                 } else {
279                     log.error("文件下载失败。 {}", client.getReplyString());
280                 }
281                 log.warn("文件【{}】下载失败,重试下载...尝试{}次", remotePath, i);
282             }
283             // 返回结果
284             return retryResult;
285         } catch (Exception ex) {
286             ex.printStackTrace();
287             log.error("下载文件异常。");
288         } finally {
289 
290         }
291         return false;
292     }
293 
294     /**
295      * 删除文件
296      * @param remotePath 远程文件,必须包含文件名
297      * @return 删除成功返回true,否则返回false
298      */
299     protected boolean deleteHandle(FTPClient client, String remotePath) {
300         try {
301             // 删除文件
302             boolean bool = client.deleteFile(remotePath);
303             if (!bool) {
304                 log.error("删除文件失败,{}", client.getReplyString());
305             }
306             return bool;
307         } catch (Exception ex) {
308             ex.printStackTrace();
309             log.error("删除文件异常。");
310         }
311         return false;
312     }
313 
314     /**
315      * 获取远程工作目录
316      * @param remotePath 远程路径
317      * @return 返回工作路径
318      */
319     private String getRemoteFilePath(String remotePath) {
320         if (StringUtils.isNotBlank(remotePath)) {
321             return remotePath.substring(0, remotePath.lastIndexOf("/") + 1);
322         }
323         return "/";
324     }
325 
326     /**
327      * 获取远程文件名
328      * @param remotePath 远程路径
329      * @return 返回文件名
330      */
331     private String getRemoteFileName(String remotePath) {
332         if (StringUtils.isNotBlank(remotePath)) {
333             return remotePath.substring(remotePath.lastIndexOf("/") + 1);
334         }
335         return "";
336     }
337 
338     /**
339      * 切换工作目录
340      * @param client ftp客户端
341      * @param dir 工作目录
342      * @return 切换成功返回true,否则返回false
343      */
344     private boolean changeDirectory(FTPClient client, String dir) {
345         try {
346             if (client == null || StringUtils.isBlank(dir)) {
347                 return false;
348             }
349 
350             String fileBackslashSeparator = "\\";
351             String fileSeparator = "/";
352 
353             if (StringUtils.contains(dir, fileBackslashSeparator)) {
354                 dir = StringUtils.replaceAll(dir, fileBackslashSeparator, fileSeparator);
355             }
356 
357             String[] dirArray = StringUtils.split(dir, fileSeparator);
358 
359             String tmp = "";
360             for (String aDirArray : dirArray) {
361                 tmp += fileSeparator + aDirArray;
362                 if (!client.changeWorkingDirectory(tmp)) {
363                     // 创建工作目录
364                     client.makeDirectory(tmp);
365                     // 切换工作目录
366                     client.changeWorkingDirectory(tmp);
367                 }
368             }
369             return true;
370         } catch (Exception ex) {
371             ex.printStackTrace();
372             log.error("切换工作目录失败。");
373         }
374         return false;
375     }
376 
377 }
View Code

5、ftp一次连接处理上传下载

 1 package com.scenetec.isv.utils.ftp.template;
 2 
 3 import com.scenetec.isv.utils.ftp.core.FtpClientFactory;
 4 import lombok.extern.slf4j.Slf4j;
 5 import org.apache.commons.net.ftp.FTPClient;
 6 import org.springframework.stereotype.Component;
 7 
 8 import javax.annotation.Resource;
 9 import java.io.InputStream;
10 import java.io.OutputStream;
11 
12 /**
13  * @author shendunyuan@scenetec.com
14  * @date 2019/1/22
15  */
16 @Slf4j
17 @Component
18 public class FtpOnceTemplate extends FtpBaseTemplate {
19 
20     @Resource
21     private FtpClientFactory factory;
22 
23     /**
24      * 上传文件
25      *
26      * @param inputStream 文件流
27      * @param remotePath 远程文件,必须包含文件名
28      * @return 上传成功返回true, 否则返回false
29      */
30     @Override
31     public boolean uploadFile(InputStream inputStream, String remotePath) {
32         // 上传
33         FTPClient client = null;
34         try {
35             // 创建对象
36             client = factory.create();
37             // 上传
38             return uploadHandle(client, inputStream, remotePath);
39         } catch (Exception ex) {
40             ex.printStackTrace();
41             log.error("上传文件异常。");
42         } finally {
43             factory.close(client);
44         }
45         return false;
46     }
47 
48     /**
49      * 下载文件
50      * @param remotePath 远程文件,必须包含文件名
51      * @param outputStream 本地文件流
52      * @return 下载成功返回true,否则返回false
53      */
54     @Override
55     public boolean downloadFile(String remotePath, OutputStream outputStream) {
56         // 下载
57         FTPClient client = null;
58         try {
59             // 获取对象
60             client = factory.create();
61             // 文件下载
62             return downloadHandle(client, remotePath, outputStream);
63         } catch (Exception ex) {
64             ex.printStackTrace();
65             log.error("下载文件异常。");
66         } finally {
67             if (client != null) {
68                 factory.close(client);
69             }
70         }
71         return false;
72     }
73 
74     /**
75      * 删除文件
76      * @param remotePath 远程文件,必须包含文件名
77      * @return 下载成功返回true,否则返回false
78      */
79     @Override
80     public boolean deleFile(String remotePath) {
81         FTPClient client = null;
82         try {
83             // 获取对象
84             client = factory.create();
85             // 删除文件
86             return deleteHandle(client, remotePath);
87         } catch (Exception ex) {
88             ex.printStackTrace();
89             log.error("删除文件异常。");
90         } finally {
91             if (client != null) {
92                 factory.close(client);
93             }
94         }
95         return false;
96     }
97 
98 }
View Code

6、ftp使用资源池处理上传下载

  1 package com.scenetec.isv.utils.ftp.template;
  2 
  3 import com.scenetec.isv.utils.ftp.core.FtpClientFactory;
  4 import lombok.extern.slf4j.Slf4j;
  5 import org.apache.commons.net.ftp.FTPClient;
  6 import org.apache.commons.net.ftp.FTPReply;
  7 import org.apache.commons.pool2.impl.GenericObjectPool;
  8 import org.springframework.stereotype.Component;
  9 
 10 import java.io.InputStream;
 11 import java.io.OutputStream;
 12 
 13 /**
 14  * @author shendunyuan@scenetec.com
 15  * @date 2018/12/20
 16  */
 17 @Slf4j
 18 @Component
 19 public class FtpPoolTemplate extends FtpBaseTemplate {
 20 
 21     private GenericObjectPool<FTPClient> ftpClientPool;
 22 
 23     public FtpPoolTemplate(FtpClientFactory ftpClientFactory) {
 24         this.ftpClientPool = new GenericObjectPool<>(ftpClientFactory);
 25     }
 26 
 27     /**
 28      * 上传文件
 29      *
 30      * @param inputStream 文件流
 31      * @param remotePath 远程文件,必须包含文件名
 32      * @return 上传成功返回true, 否则返回false
 33      */
 34     @Override
 35     public boolean uploadFile(InputStream inputStream, String remotePath) {
 36         // 上传
 37         FTPClient client = null;
 38         try {
 39             // 从池中获取对象
 40             client = getFtpClient();
 41             // 上传
 42             return uploadHandle(client, inputStream, remotePath);
 43         } catch (Exception ex) {
 44             ex.printStackTrace();
 45             log.error("上传文件异常。");
 46         } finally {
 47             // 将对象放回池中
 48             if (client != null) {
 49                 ftpClientPool.returnObject(client);
 50             }
 51         }
 52         return false;
 53     }
 54 
 55     /**
 56      * 下载文件
 57      * @param remotePath 远程文件,必须包含文件名
 58      * @param outputStream 本地文件流
 59      * @return 下载成功返回true,否则返回false
 60      */
 61     @Override
 62     public boolean downloadFile(String remotePath, OutputStream outputStream) {
 63         // 下载
 64         FTPClient client = null;
 65         try {
 66             // 从池中获取对象
 67             client = getFtpClient();
 68             // 下载
 69             return downloadHandle(client, remotePath, outputStream);
 70         } catch (Exception ex) {
 71             ex.printStackTrace();
 72             log.error("下载文件异常。");
 73         } finally {
 74             if (client != null) {
 75                 ftpClientPool.returnObject(client);
 76             }
 77         }
 78         return false;
 79     }
 80 
 81     /**
 82      * 删除文件
 83      * @param remotePath 远程文件,必须包含文件名
 84      * @return 下载成功返回true,否则返回false
 85      */
 86     @Override
 87     public boolean deleFile(String remotePath) {
 88         FTPClient client = null;
 89         try {
 90             // 从池中获取对象
 91             client = getFtpClient();
 92             // 删除文件
 93             return deleteHandle(client, remotePath);
 94         } catch (Exception ex) {
 95             ex.printStackTrace();
 96             log.error("删除文件异常。");
 97         } finally {
 98             if (client != null) {
 99                 ftpClientPool.returnObject(client);
100             }
101         }
102         return false;
103     }
104 
105 
106     /**
107      * 验证连接是否成功
108      * @return 连接登录成功返回true,否则返回false
109      */
110     private FTPClient getFtpClient () {
111         FTPClient client = null;
112         try {
113             while (true) {
114                 // 获取客户端
115                 client = ftpClientPool.borrowObject();
116                 // 验证客户端
117                 if (client == null) {
118                     continue;
119                 } else {
120                     if (!client.isConnected() || !FTPReply.isPositiveCompletion(client.getReplyCode())) {
121                         ftpClientPool.invalidateObject(client);
122                     } else {
123                         break;
124                     }
125                 }
126             }
127         } catch (Exception ex) {
128             ex.printStackTrace();
129         }
130         return client;
131     }
132 
133 }
View Code

7、ftp部分依赖配置

 1 <dependencies>
 2         <dependency>
 3             <groupId>org.apache.commons</groupId>
 4             <artifactId>commons-lang3</artifactId>
 5             <version>3.7</version>
 6         </dependency>
 7         <dependency>
 8             <groupId>org.slf4j</groupId>
 9             <artifactId>slf4j-api</artifactId>
10             <version>1.7.25</version>
11         </dependency>
12         <dependency>
13             <groupId>commons-net</groupId>
14             <artifactId>commons-net</artifactId>
15             <version>3.3</version>
16         </dependency>
17         <dependency>
18             <groupId>org.projectlombok</groupId>
19             <artifactId>lombok</artifactId>
20             <version>1.16.8</version>
21             <scope>provided</scope>
22         </dependency>
23         <dependency>
24             <groupId>org.apache.commons</groupId>
25             <artifactId>commons-pool2</artifactId>
26             <version>2.5.0</version>
27         </dependency>
28     </dependencies>
View Code

8、ftp测试类

 1 package com.scenetec.isv.operation.ftp;
 2 
 3 import com.scenetec.isv.operation.ISVOperationManagerApplication;
 4 import com.scenetec.isv.utils.ftp.template.FtpOnceTemplate;
 5 import com.scenetec.isv.utils.ftp.template.FtpPoolTemplate;
 6 import org.junit.Test;
 7 import org.junit.runner.RunWith;
 8 import org.springframework.beans.factory.annotation.Autowired;
 9 import org.springframework.boot.test.context.SpringBootTest;
10 import org.springframework.test.context.junit4.SpringRunner;
11 
12 import javax.annotation.Resource;
13 import java.io.File;
14 
15 /**
16  * @author shendunyuan@scenetec.com
17  * @date 2018/12/20
18  */
19 @SpringBootTest(classes = ISVOperationManagerApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
20 @RunWith(SpringRunner.class)
21 public class FtpClientPoolTest {
22 
23     @Autowired
24     private FtpPoolTemplate ftpPoolTemplate;
25     @Resource
26     private FtpOnceTemplate ftpOnceTemplate;
27 
28     private String localPath = "/Users/sdy/test/isv/platform.cer";
29     private String localDownPath = "/Users/sdy/test/isv/2019/111test.cer";
30     private String remotePath = "/2019/111.cer";
31 
32     @Test
33     public void upload() {
34         boolean bool = ftpPoolTemplate.uploadFile(localPath, remotePath);
35         if (bool) {
36             System.out.println("success");
37         } else {
38             System.out.println("failed");
39         }
40     }
41 
42     @Test
43     public void up() {
44         boolean bool = ftpOnceTemplate.uploadFile(localPath, remotePath);
45         if (bool) {
46             System.out.println("success");
47         } else {
48             System.out.println("failed");
49         }
50     }
51 
52     @Test
53     public void uploadFile() {
54         File file = new File(localPath);
55         boolean bool = ftpPoolTemplate.uploadFile(file, remotePath);
56         if (bool) {
57             System.out.println("success");
58         } else {
59             System.out.println("failed");
60         }
61     }
62 
63     @Test
64     public void downloadFile() {
65         boolean bool = ftpPoolTemplate.downloadFile(remotePath, localDownPath);
66         if (bool) {
67             System.out.println("success");
68         } else {
69             System.out.println("failed");
70         }
71     }
72 
73     @Test
74     public void deleteFile() {
75         boolean bool = ftpPoolTemplate.deleteFile(remotePath);
76         if (bool) {
77             System.out.println("success");
78         } else {
79             System.out.println("failed");
80         }
81     }
82 }
View Code

注意:ftp多线程处理时容易超时,目前没有找到更好的处理办法。

完整项目代码请参见:https://github.com/sxpdy8571/ftpUtils/tree/develop

 

posted @ 2019-01-13 20:22  sxpdy  阅读(1431)  评论(0编辑  收藏  举报