一、SpringBoot整合FTP使用
1、引入依赖
这里引用 Apache commons-net依赖,用于FTP客户端操作。
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
<version>3.11.0</version>
</dependency>
2、FTP配置信息类
(1)配置文件添加 ftp配置信息。
# 文件上传相关
file:
# FTP文件相关
ftp:
host: 192.168.xxx.xxx
port: 21
username: zhangsan
password: xxxxxx
basePath: /ftpv
filePathPrefix: http://192.168.xxx.xxx:9090/viewFile
(2)ftp自定义配置信息类
/**
* ftp自定义配置信息类
*/
@Data
@Configuration
public class FtpProperties {
/**
* ftp服务器的地址
*/
@Value("${file.ftp.host}")
private String ftpHost;
/**
* ftp服务器的端口号(连接端口号)
*/
@Value("${file.ftp.port}")
private int ftpPort;
/**
* ftp的用户名
*/
@Value("${file.ftp.username}")
private String ftpUsername;
/**
* ftp的密码
*/
@Value("${file.ftp.password}")
private String ftpPassword;
/**
* ftp用户上传的根目录
*/
@Value("${file.ftp.basePath}")
private String ftpBasePath;
/**
* http访问文件的路径前缀,配合Nginx静态资源访问
*/
@Value("${file.ftp.filePathPrefix}")
private String ftpFilePathPrefix;
}
3、FTP服务工具类
/**
* FTP服务工具类
*/
@Slf4j
public class FtpUtils {
/**
* 获取 FTPClient对象
*
* @param ftpHost FTP主机服务器
* @param ftpPort FTP端口 默认为21
* @param ftpUserName FTP 登录密码
* @param ftpPassword FTP登录密码
* @return FTPClient对象
*/
private static FTPClient getFTPClient(String ftpHost, int ftpPort, String ftpUserName, String ftpPassword) {
/**
* 创建 FTPClient对象(对于连接ftp服务器,以及上传和上传都必须要用到一个对象)
*/
try {
FTPClient ftpClient = new FTPClient();
/**
* 连接 FTP服务
*/
// 设置编码
ftpClient.setControlEncoding("UTF-8");
// 设置连接超时时间(单位:毫秒)
ftpClient.setConnectTimeout(10 * 1000);
// 连接
ftpClient.connect(ftpHost, ftpPort);
// 登录
ftpClient.login(ftpUserName, ftpPassword);
/**
* ftpClient.getReplyCode():接受状态码(如果成功,返回230,如果失败返回503)
* FTPReply.isPositiveCompletion():如果连接成功返回true,否则返回false
*/
if (!FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) {
log.error("未连接到FTP服务,用户名或密码错误");
// 连接失败,断开连接
ftpClient.disconnect();
return null;
} else {
log.info("连接到FTP服务成功");
// 设置二进制方式传输文件
ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
// 设置被动工作模式,文件传输端口设置,否则文件上传不成功,也不报错
ftpClient.enterLocalPassiveMode();
}
return ftpClient;
} catch (SocketException e) {
e.printStackTrace();
log.error("FTP的IP地址错误,请正确配置。");
} catch (IOException e) {
e.printStackTrace();
log.error("FTP的端口错误,请正确配置。");
} catch (Exception e) {
e.printStackTrace();
log.error("获取ftp客户端异常");
}
return null;
}
/**
* 断开 FTPClient对象
*/
private static void closeConnect(FTPClient ftpClient) {
try {
if (ftpClient != null && ftpClient.isConnected()) {
ftpClient.logout();
// 断开ftp的连接
ftpClient.disconnect();
log.info("关闭ftp客户端成功");
}
} catch (Exception e) {
e.printStackTrace();
log.error("关闭ftp客户端异常");
}
}
/**
* 创建文件夹
*
* @param ftpHost FTP主机服务器
* @param ftpPort FTP端口 默认为21
* @param ftpUserName FTP 登录密码
* @param ftpPassword FTP登录密码
* @param ftpBasePath FTP用户上传的根目录
* @param dirPath 需要创建的文件夹,多层使用/隔开
* @return
*/
public static boolean createDirectory(String ftpHost, int ftpPort, String ftpUserName, String ftpPassword, String ftpBasePath, String dirPath) {
FTPClient ftpClient = FtpUtils.getFTPClient(ftpHost, ftpPort, ftpUserName, ftpPassword);
try {
/**
* 切换到ftp的服务器路径。
* FTP服务为FTP虚拟用户默认了根目录,所以我们可以切换也可以不切换,结果是一样的,都会到用户的根目录下。推荐显示指定。
* FTP服务会判断文件夹已存在,不会创建,不存在,则会创建。
*/
ftpClient.changeWorkingDirectory(ftpBasePath);
if (StringUtils.isBlank(dirPath)) {
return false;
}
String[] dirPathArr = dirPath.split("/");
for (String dir : dirPathArr) {
if (StringUtils.isNotBlank(dir)) {
ftpClient.makeDirectory(dir);
// 切换到ftp的创建目录
ftpClient.changeWorkingDirectory(dir);
}
}
return true;
} catch (IOException e) {
e.printStackTrace();
log.error("创建文件夹异常");
} finally {
closeConnect(ftpClient);
}
return false;
}
/**
* 查询指定路径下的所有文件的文件名
*
* @param ftpHost FTP主机服务器
* @param ftpPort FTP端口 默认为21
* @param ftpUserName FTP 登录密码
* @param ftpPassword FTP登录密码
* @param dirPath 查询指定路径
* @return
*/
public static List<String> listFileName(String ftpHost, int ftpPort, String ftpUserName, String ftpPassword, String dirPath) {
if (StringUtils.isBlank(dirPath)) {
return null;
}
FTPClient ftpClient = FtpUtils.getFTPClient(ftpHost, ftpPort, ftpUserName, ftpPassword);
// 获得指定目录下所有文件名
FTPFile[] ftpFiles = null;
try {
//ftpClient.enterLocalPassiveMode(); // 列出路径下的所有文件的文件名
ftpFiles = ftpClient.listFiles(dirPath);
} catch (IOException e) {
e.printStackTrace();
log.info("关闭ftp客户端成功");
return null;
} finally {
closeConnect(ftpClient);
}
List<String> fileNameList = new LinkedList<String>();
for (int i = 0; ftpFiles != null && i < ftpFiles.length; i++) {
FTPFile file = ftpFiles[i];
if (file.isFile()) {
fileNameList.add(file.getName());
}
}
return fileNameList;
}
/**
* 上传文件到ftp服务
*
* @param ftpHost FTP主机服务器
* @param ftpPort FTP端口 默认为21
* @param ftpUserName FTP 登录密码
* @param ftpPassword FTP登录密码
* @param ftpBasePath FTP用户上传的根目录
* @param fileDirPath 上传的文件存储目录
* @param fileName 上传的文件名
* @param is 上传的文件输入流
*/
public static boolean uploadFileToFtp(String ftpHost, int ftpPort, String ftpUserName, String ftpPassword, String ftpBasePath, String fileDirPath, String fileName, InputStream is) {
FTPClient ftpClient = FtpUtils.getFTPClient(ftpHost, ftpPort, ftpUserName, ftpPassword);
boolean result = false;
try {
// 创建文件存储目录
FtpUtils.createDirectory(ftpHost, ftpPort, ftpUserName, ftpPassword, ftpBasePath, fileDirPath);
// 切换到ftp的文件目录,即文件上传目录
ftpClient.changeWorkingDirectory(fileDirPath);
ftpClient.setControlEncoding("UTF-8");
ftpClient.setBufferSize(1024 * 10);
// 设置文件类型为二进制方式传输文件
ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
ftpClient.enterLocalPassiveMode();
ftpClient.setDefaultTimeout(18000);
ftpClient.setConnectTimeout(6000);
ftpClient.setSoTimeout(6000);
result = ftpClient.storeFile(fileName, is);
} catch (IOException e) {
log.error("上传文件到ftp服务失败:{}", e);
} finally {
closeConnect(ftpClient);
}
return result;
}
/**
* 从FTP中获取文件的输入流
*
* @param ftpHost FTP主机服务器
* @param ftpPort FTP端口 默认为21
* @param ftpUserName FTP 登录密码
* @param ftpPassword FTP登录密码
* @param ftpFilePath ftp文件路径,根目录开始
* @return
*/
public static InputStream getInputStreamOfFtpFile(String ftpHost, int ftpPort, String ftpUserName, String ftpPassword, String ftpFilePath) {
FTPClient ftpClient = FtpUtils.getFTPClient(ftpHost, ftpPort, ftpUserName, ftpPassword);
InputStream is = null;
try {
is = ftpClient.retrieveFileStream(ftpFilePath);
} catch (IOException e) {
e.printStackTrace();
log.error("获取文件输入流异常");
} finally {
closeConnect(ftpClient);
}
return is;
}
/**
* 删除ftp文件
*
* @param ftpHost FTP主机服务器
* @param ftpPort FTP端口 默认为21
* @param ftpUserName FTP 登录密码
* @param ftpPassword FTP登录密码
* @param ftpFilePath ftp文件路径,根目录开始
* @return
*/
public static boolean deleteFtpFile(String ftpHost, int ftpPort, String ftpUserName, String ftpPassword, String ftpFilePath) {
FTPClient ftpClient = FtpUtils.getFTPClient(ftpHost, ftpPort, ftpUserName, ftpPassword);
boolean result = false;
try {
result = ftpClient.deleteFile(ftpFilePath);
} catch (IOException e) {
log.error("删除ftp文件失败:{}", e);
} finally {
closeConnect(ftpClient);
}
return result;
}
}
4、FTP工具类测试
在项目,通常我们提供一个 FtpService实现类来封装 FTP服务工具类。
这里进行 FTP工具类测试即可。
public static void main(String[] args) throws Exception {
FtpProperties ftpProperties = getFtpProperties();
获取 FTPClient对象
//FTPClient ftpClient = FtpUtils.getFTPClient(ftpProperties.getFtpHost(), ftpProperties.getFtpPort(), ftpProperties.getFtpUsername(), ftpProperties.getFtpPassword());
断开 FTPClient对象
//FtpUtils.closeConnect(ftpClient);
// 创建文件夹
//String dirPath = "dev_dir1/d11/d12";
//FtpUtils.createDirectory(ftpProperties.getFtpHost(), ftpProperties.getFtpPort(), ftpProperties.getFtpUsername(), ftpProperties.getFtpPassword(), ftpProperties.getFtpBasePath(), dirPath);
// 查询指定路径下的所有文件的文件名
//String dirPath = "/dev_dir1";
//List<String> fileNameList = FtpUtils.listFileName(ftpProperties.getFtpHost(), ftpProperties.getFtpPort(), ftpProperties.getFtpUsername(), ftpProperties.getFtpPassword(), dirPath);
//for (String fileName : Optional.ofNullable(fileNameList).orElse(new ArrayList<>())) {
// System.out.println(fileName);
//}
// 上传文件到ftp服务
//String fileDirPath = "dev_dir1";
//String fileName = "dev_uploadFile001.jpg";
//InputStream is = new FileInputStream("D:\\TempFiles\\598a80e12f9ad-中文.jpg");
//FtpUtils.uploadFileToFtp(ftpProperties.getFtpHost(), ftpProperties.getFtpPort(), ftpProperties.getFtpUsername(), ftpProperties.getFtpPassword(), ftpProperties.getFtpBasePath(), fileDirPath, fileName, is);
// 从FTP中获取文件的输入流
//String ftpFilePath = "dev_dir1/dev_uploadFile001.jpg";
//InputStream inputStreamOfFtpFile = FtpUtils.getInputStreamOfFtpFile(ftpProperties.getFtpHost(), ftpProperties.getFtpPort(), ftpProperties.getFtpUsername(), ftpProperties.getFtpPassword(), ftpFilePath);
//FileUtils.copyInputStreamToFile(inputStreamOfFtpFile, new File("D:\\TempFiles\\dev_uploadFile001.jpg"));
//String ftpFilePath = "dev_dir1/zs_111.txt";
//InputStream inputStreamOfFtpFile = FtpUtils.getInputStreamOfFtpFile(ftpProperties.getFtpHost(), ftpProperties.getFtpPort(), ftpProperties.getFtpUsername(), ftpProperties.getFtpPassword(), ftpFilePath);
//FileUtils.copyInputStreamToFile(inputStreamOfFtpFile, new File("D:\\TempFiles\\zs_111.txt"));
// 删除ftp文件
String ftpFilePath = "dev_dir1/dev_uploadFile002.jpg";
boolean result = FtpUtils.deleteFtpFile(ftpProperties.getFtpHost(), ftpProperties.getFtpPort(), ftpProperties.getFtpUsername(), ftpProperties.getFtpPassword(), ftpFilePath);
log.info("删除ftp文件结果,result={}", result);
}
– 求知若饥,虚心若愚。