SpringBoot整合自定義FTP文件鏈接池

說明:經過GenericObjectPool實現的FTP鏈接池,記錄一下以供之後使用
環境:
JDK版本1.8
框架 :springboot2.1
文件服務器: Serv-U
1.引入依賴java

<!--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.propertiesweb

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.建立配置類FtpConfigspring

package com.hcq.demo.util;apache

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

import java.util.HashMap;
import java.util.Map;
import java.util.Set;服務器

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

@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;dom

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;ide

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 */@Componentpublic 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)); }

相關文章
相關標籤/搜索