說明:通過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));
}
}
---------------------
作者:Keepalived。
來源:CSDN
原文:https://blog.csdn.net/qq_39914581/article/details/88660133
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!