SpringBoot整合自定义FTP文件连接池

说明:通过GenericObjectPool实现的FTP连接池,记录一下以供以后使用 环境: JDK版本1.8 框架 :springboot2.1 文件服务器: Serv-U 1.引入依赖

<!--ftp文件上传--> <dependency> <groupId>commons-net</groupId> <artifactId>commons-net</artifactId> <version>3.3</version> </dependency> <!--自定义连接池--> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> <version>2.4.2</version> </dependency> 2.创建ftp.properties

ftp.Host=192.168.xx.xx 本机ip ftp.Port=21 ftp.UserName=root ftp.PassWord=root ftp.workDir=/images ftp.encoding=utf-8 ftp.root=/ ftp.MaxTotal=100 ftp.MinIdel=2 ftp.MaxIdle=5 ftp.MaxWaitMillis=3000 3.创建配置类FtpConfig

package com.hcq.demo.util;

import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.PropertySource; import org.springframework.stereotype.Component;

import java.util.HashMap; import java.util.Map; import java.util.Set;

/** * fileName:FtpConfig * description: * author:hcq * createTime:2019-03-15 15:04 */

@Component @ConfigurationProperties(prefix="ftp") @PropertySource("classpath:ftp.properties") public class FtpConfig { private String Host; private int Port; private String UserName; private String PassWord; private String workDir; private String encoding; private String root; private int MaxTotal; private int MinIdel; private int MaxIdle; private int MaxWaitMillis; .......省略get set } 4.创建FtpClientFactory工厂类

package com.hcq.demo.util;

import org.apache.commons.net.ftp.FTP; import org.apache.commons.net.ftp.FTPClient; import org.apache.commons.pool2.PooledObject; import org.apache.commons.pool2.impl.DefaultPooledObject; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.apache.commons.pool2.PooledObjectFactory;

import java.io.IOException;

/** * fileName:FtpClientFactory * description: * author:hcq * createTime:2019-03-18 19:49 */ @Component public class FtpClientFactory implements PooledObjectFactory<FTPClient> { @Autowired FtpConfig config; //创建连接到池中 @Override public PooledObject<FTPClient> makeObject() { FTPClient ftpClient = new FTPClient();//创建客户端实例 return new DefaultPooledObject<>(ftpClient); } //销毁连接,当连接池空闲数量达到上限时,调用此方法销毁连接 @Override public void destroyObject(PooledObject<FTPClient> pooledObject) { FTPClient ftpClient = pooledObject.getObject(); try { ftpClient.logout(); if (ftpClient.isConnected()) { ftpClient.disconnect(); } } catch (IOException e) { throw new RuntimeException("Could not disconnect from server.", e); } } //链接状态检查 @Override public boolean validateObject(PooledObject<FTPClient> pooledObject) { FTPClient ftpClient = pooledObject.getObject(); try { return ftpClient.sendNoOp(); } catch (IOException e) { return false; } } //初始化连接 @Override public void activateObject(PooledObject<FTPClient> pooledObject) throws Exception { FTPClient ftpClient = pooledObject.getObject(); ftpClient.connect(config.getHost(),config.getPort()); ftpClient.login(config.getUserName(), config.getPassWord()); ftpClient.setControlEncoding(config.getEncoding()); ftpClient.changeWorkingDirectory(config.getWorkDir()); ftpClient.setFileType(FTP.BINARY_FILE_TYPE);//设置上传文件类型为二进制,否则将无法打开文件 } //钝化连接,使链接变为可用状态 @Override public void passivateObject(PooledObject<FTPClient> pooledObject) throws Exception { FTPClient ftpClient = pooledObject.getObject(); try { ftpClient.changeWorkingDirectory(config.getRoot()); ftpClient.logout(); if (ftpClient.isConnected()) { ftpClient.disconnect(); } } catch (IOException e) { throw new RuntimeException("Could not disconnect from server.", e); } } //用于连接池中获取pool属性 public FtpConfig getConfig() { return config; } } 5.创建FtpPool连接池

package com.hcq.demo.util;

import org.apache.commons.net.ftp.FTPClient; import org.apache.commons.pool2.impl.GenericObjectPool; import org.apache.commons.pool2.impl.GenericObjectPoolConfig; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component;

/** * fileName:ftpPool * description:FTP连接池 * 1.可以获取池中空闲链接 * 2.可以将链接归还到池中 * 3.当池中空闲链接不足时,可以创建链接 * author:hcq * createTime:2019-03-16 9:59 */ @Component public class FtpPool { FtpClientFactory factory; private final GenericObjectPool<FTPClient> internalPool; //初始化连接池 public FtpPool(@Autowired FtpClientFactory factory){ this.factory=factory; FtpConfig config = factory.getConfig(); GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig(); poolConfig.setMaxTotal(config.getMaxTotal()); poolConfig.setMinIdle(config.getMinIdel()); poolConfig.setMaxIdle(config.getMaxIdle()); poolConfig.setMaxWaitMillis(config.getMaxWaitMillis()); this.internalPool = new GenericObjectPool<FTPClient>(factory,poolConfig); } //从连接池中取连接 public FTPClient getFTPClient() { try { return internalPool.borrowObject(); } catch (Exception e) { e.printStackTrace(); return null; } } //将链接归还到连接池 public void returnFTPClient(FTPClient ftpClient) { try { internalPool.returnObject(ftpClient); } catch (Exception e) { e.printStackTrace(); } } /** * 销毁池子 */ public void destroy() { try { internalPool.close(); } catch (Exception e) { e.printStackTrace(); } } }

6.创建FtpUtil类

package com.hcq.demo.util;

import org.apache.commons.net.ftp.FTPClient; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.io.ResourceLoader; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Component; import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse; import java.io.*; import java.util.UUID;

/** * fileName:FTP工具类 * description:提供文件上传和下载 * author:hcq * createTime:2019-03-16 8:55 */ @Component public class FtpUtil { @Autowired FtpConfig config; @Autowired private ResourceLoader resourceLoader; @Autowired FtpPool pool; /** * Description: 向FTP服务器上传文件 * * @Version2.0 * @param file * 上传到FTP服务器上的文件 * @return * 成功返回文件名,否则返回null */ public String upload(MultipartFile file) throws Exception { FTPClient ftpClient = pool.getFTPClient(); //开始进行文件上传 String fileName=UUID.randomUUID()+file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".")); InputStream input=file.getInputStream(); try { boolean result=ftpClient.storeFile(fileName,input);//执行文件传输 if(!result){//上传失败 throw new RuntimeException("上传失败"); } }catch(Exception e){ e.printStackTrace(); return null; }finally {//关闭资源 input.close(); System.out.println("开始归还连接"); pool.returnFTPClient(ftpClient);//归还资源 } return fileName; } /** * Description: 从FTP服务器下载文件 * * @Version1.0 * @param fileName * FTP服务器中的文件名 * @param resp * 响应客户的响应体 */ public void downLoad(String fileName,HttpServletResponse resp) throws IOException { FTPClient ftpClient = pool.getFTPClient(); resp.setContentType("application/force-download");// 设置强制下载不打开 MIME resp.addHeader("Content-Disposition", "attachment;fileName="+fileName);// 设置文件名 //将文件直接读取到响应体中 OutputStream out = resp.getOutputStream(); ftpClient.retrieveFile(config.getWorkDir()+"/"+fileName, out); out.flush(); out.close(); pool.returnFTPClient(ftpClient); } /** * Description: 从FTP服务器读取图片 * * @Version1.0 * @param fileName * 需要读取的文件名 * @return * 返回文件对应的Entity */ public ResponseEntity show(String fileName){ String username=config.getUserName(); String password=config.getPassWord(); String host=config.getHost(); String work=config.getWorkDir(); //ftp://root:root@192.168.xx.xx/+fileName return ResponseEntity.ok(resourceLoader.getResource("ftp://"+username+":"+password+"@"+host+work+"/"+fileName)); }

}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券