springcloud整合FTPClient
原文链接: https://blog.csdn.net/boomLJiE/article/details/89372738
近期需要做ftp上传图片,因此做个记录,免得以后忘记了!
ftp是连的本地windows电脑的ftp,因为是家庭版,没办法设置用户,因此是没有账号密码,就可以访问的,一开始没填账号密码,老是提示上传失败,后面百度了很久之后才知道,使用默认的ftp账号就可以了
首先pom文件引用相关的包
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
<version>3.6</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.6.2</version>
</dependency>
yml配置
ftp:
host: 172.16.1.158
port: 21
username: ftp
password:
#是否被动模式
passiveMode: true
ftp配置类
@Data
@Component
public class FtpConfig {
@Value("${ftp.host}")
private String host;
@Value("${ftp.port}")
private int port;
@Value("${ftp.username}")
private String username;
@Value("${ftp.password}")
private String password;
@Value("${ftp.passiveMode}")
private Boolean passiveMode;
}
FtpClient工厂类:
@Component
public class FtpClientFactory implements PooledObjectFactory<FTPClient> {
@Autowired
FtpConfig ftpConfig;
/**
* 创建连接到池中
* @return
*/
@Override
public PooledObject<FTPClient> makeObject() {
//创建客户端实例
FTPClient ftpClient = new FTPClient();
return new DefaultPooledObject<FTPClient>(ftpClient);
}
/**
* 销毁连接,当连接池空闲数量达到上限时,调用此方法销毁连接
* @param pooledObject
*/
@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);
}
}
/**
* 链接状态检查
* @param pooledObject
* @return
*/
@Override
public boolean validateObject(PooledObject<FTPClient> pooledObject) {
FTPClient ftpClient = pooledObject.getObject();
try {
return ftpClient.sendNoOp();
} catch (IOException e) {
return false;
}
}
/**
* 初始化连接
* @param pooledObject
* @throws Exception
*/
@Override
public void activateObject(PooledObject<FTPClient> pooledObject) throws Exception {
FTPClient ftpClient = pooledObject.getObject();
ftpClient.connect(ftpConfig.getHost(), ftpConfig.getPort());
ftpClient.login(ftpConfig.getUsername(), ftpConfig.getPassword());
//设置上传文件类型为二进制,否则将无法打开文件
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
// 开启服务器对UTF-8的支持,如果服务器支持就用UTF-8编码,否则就使用本地编码(GBK).
String LOCAL_CHARSET = "GBK";
if (FTPReply.isPositiveCompletion(ftpClient.sendCommand("OPTS UTF8", "ON"))) {
LOCAL_CHARSET = "UTF-8";
}
ftpClient.setControlEncoding(LOCAL_CHARSET);
}
/**
* 钝化连接,使链接变为可用状态
* @param pooledObject
* @throws Exception
*/
@Override
public void passivateObject(PooledObject<FTPClient> pooledObject) throws Exception {
FTPClient ftpClient = pooledObject.getObject();
try {
ftpClient.changeWorkingDirectory("/");
ftpClient.logout();
if (ftpClient.isConnected()) {
ftpClient.disconnect();
}
} catch (IOException e) {
throw new RuntimeException("Could not disconnect from server.", e);
}
}
}
FptPool创建:
@Component
public class FtpPool {
FtpClientFactory factory;
private final GenericObjectPool<FTPClient> internalPool;
/**
* 初始化连接池
* @param factory
*/
public FtpPool(@Autowired FtpClientFactory factory) {
this.factory = factory;
GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
poolConfig.setMaxTotal(20);
poolConfig.setMinIdle(1);
poolConfig.setMaxIdle(8);
poolConfig.setMaxWaitMillis(3000);
this.internalPool = new GenericObjectPool<FTPClient>(factory, poolConfig);
}
/**
* 从连接池中取连接
* @return
*/
public FTPClient getFTPClient() {
try {
return internalPool.borrowObject();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 将链接归还到连接池
* @param ftpClient
*/
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();
}
}
}
FtpUtil工具类
@Component
public class FtpUtil {
@Autowired
FtpPool pool;
@Autowired
FtpConfig ftpConfig;
/**
* Description: 向FTP服务器上传文件
*
* @param file 上传到FTP服务器上的文件
* @return 成功返回文件名,否则返回null
* @Version2.0
*/
public void upload(File file, String workDirs, String fileName) throws Exception {
FTPClient ftpClient = pool.getFTPClient();
//开始进行文件上传
if(StringUtils.isBlank(fileName)) {
fileName = file.getName();
}
InputStream input = new FileInputStream(file);
String[] ret = new String[2];
if (input.available() == 0) {
throw new BusinessException(ResultEnum.validFail.result().getCode(), "文件大小为0");
}
try {
ftpClient.setControlEncoding("UTF-8");
String remote = new String(workDirs + File.separator + fileName);
// 设置上传目录(没有则创建)
if (!createDir(workDirs, ftpClient)) {
throw new BusinessException(ResultEnum.validFail.result().getCode(), "切入FTP目录失败:" + workDirs);
}
//设置被动模式
ftpClient.enterLocalPassiveMode();
boolean result = ftpClient.storeUniqueFile(remote, input);
if (!result) {
//上传失败
throw new BusinessException(ResultEnum.validFail.result().getCode(), "上传失败文件");
}
} catch (Exception e) {
throw new BusinessException(ResultEnum.validFail.result().getCode(), "上传失败");
} finally {//关闭资源
input.close();
System.out.println("开始归还连接");
//归还资源
pool.returnFTPClient(ftpClient);
}
}
/**
* 创建目录(有则切换目录,没有则创建目录)
*
* @param dir
* @return
*/
public boolean createDir(String dir, FTPClient ftpClient) {
if (StringUtils.isBlank(dir)) {
return true;
}
String path;
try {
//目录编码,解决中文路径问题
path = new String(dir.toString().getBytes("UTF-8"), "iso-8859-1");
//尝试切入目录
if (ftpClient.changeWorkingDirectory(path)) {
return true;
}
String[] arr = dir.split("/");
StringBuffer sbfDir = new StringBuffer();
//循环生成子目录
for (String s : arr) {
sbfDir.append("/").append(s);
//目录编码,解决中文路径问题
path = new String(sbfDir.toString().getBytes("GBK"), "iso-8859-1");
//尝试切入目录
if (ftpClient.changeWorkingDirectory(path)) {
continue;
}
if (!ftpClient.makeDirectory(path)) {
System.out.println("[失败]ftp创建目录:" + sbfDir.toString());
return false;
}
System.out.println("[成功]创建ftp目录:" + sbfDir.toString());
}
//将目录切换至指定路径
return ftpClient.changeWorkingDirectory(path);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
}
然后调ftpUtil的方法就可以了,自测结果是正常的!但是感觉目前还不到需要使用对象池的地步,因此做个记录,免得以后需要用找不到
以上是 springcloud整合FTPClient 的全部内容, 来源链接: utcz.com/z/517565.html