|
|
@@ -0,0 +1,356 @@
|
|
|
+package com.uas.eis.utils;
|
|
|
+
|
|
|
+import org.apache.commons.net.ftp.FTP;
|
|
|
+import org.apache.commons.net.ftp.FTPClient;
|
|
|
+import org.apache.commons.net.ftp.FTPFile;
|
|
|
+import org.apache.commons.net.ftp.FTPReply;
|
|
|
+import org.slf4j.Logger;
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
+
|
|
|
+import java.io.*;
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.List;
|
|
|
+
|
|
|
+/**
|
|
|
+ * FTP工具类 - 实现文件流的读取
|
|
|
+ */
|
|
|
+public class FTPUtil {
|
|
|
+
|
|
|
+ private static final Logger logger = LoggerFactory.getLogger(FTPUtil.class);
|
|
|
+
|
|
|
+ private static final String DEFAULT_CHARSET = "UTF-8";
|
|
|
+ private static final int DEFAULT_TIMEOUT = 30000;
|
|
|
+ private static final int DEFAULT_BUFFER_SIZE = 1024 * 1024; // 1MB
|
|
|
+ private static String USER = "mes"; //用户名
|
|
|
+ private static String PWD = "plantuftp123"; //密码
|
|
|
+ public static String IP = "172.16.0.118";
|
|
|
+ public static String currentDir ="/home/mes";
|
|
|
+ public static FTPClient getFTPClient() {
|
|
|
+ FTPClient ftpClient = new FTPClient();
|
|
|
+ try {
|
|
|
+ ftpClient.setConnectTimeout(DEFAULT_TIMEOUT);
|
|
|
+ ftpClient.connect(IP, 21);
|
|
|
+
|
|
|
+ int reply = ftpClient.getReplyCode();
|
|
|
+ if (!FTPReply.isPositiveCompletion(reply)) {
|
|
|
+ logger.error("FTP服务器拒绝连接,响应码: {}", reply);
|
|
|
+ ftpClient.disconnect();
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ boolean loginResult = ftpClient.login(USER, PWD);
|
|
|
+ if (!loginResult) {
|
|
|
+ logger.error("FTP登录失败");
|
|
|
+ ftpClient.disconnect();
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ ftpClient.setControlEncoding(DEFAULT_CHARSET);
|
|
|
+ ftpClient.setBufferSize(DEFAULT_BUFFER_SIZE);
|
|
|
+ ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
|
|
|
+ ftpClient.enterLocalPassiveMode();
|
|
|
+ logger.info("FTP连接成功: {}", IP);
|
|
|
+ } catch (IOException e) {
|
|
|
+ logger.error("FTP连接异常", e);
|
|
|
+ closeFTPClient(ftpClient);
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ return ftpClient;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 关闭FTP连接
|
|
|
+ *
|
|
|
+ * @param ftpClient FTP客户端
|
|
|
+ */
|
|
|
+ public static void closeFTPClient(FTPClient ftpClient) {
|
|
|
+ if (ftpClient != null && ftpClient.isConnected()) {
|
|
|
+ try {
|
|
|
+ ftpClient.logout();
|
|
|
+ ftpClient.disconnect();
|
|
|
+ logger.info("FTP连接已关闭");
|
|
|
+ } catch (IOException e) {
|
|
|
+ logger.error("关闭FTP连接异常", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 读取FTP文件为输入流
|
|
|
+ *
|
|
|
+ * @param ftpClient FTP客户端
|
|
|
+ * @param remotePath 远程文件路径
|
|
|
+ * @return InputStream
|
|
|
+ */
|
|
|
+ public static InputStream readFileAsStream(FTPClient ftpClient, String remotePath) {
|
|
|
+ try {
|
|
|
+ InputStream inputStream = ftpClient.retrieveFileStream(remotePath);
|
|
|
+ if (inputStream == null) {
|
|
|
+ logger.error("读取文件失败: {}", remotePath);
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ logger.info("成功读取文件流: {}", remotePath);
|
|
|
+ return inputStream;
|
|
|
+ } catch (IOException e) {
|
|
|
+ logger.error("读取文件流异常: {}", remotePath, e);
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 读取FTP文件到本地
|
|
|
+ *
|
|
|
+ * @param ftpClient FTP客户端
|
|
|
+ * @param remotePath 远程文件路径
|
|
|
+ * @param localPath 本地文件路径
|
|
|
+ * @return 是否成功
|
|
|
+ */
|
|
|
+ public static boolean downloadFile(FTPClient ftpClient, String remotePath, String localPath) {
|
|
|
+ File localFile = new File(localPath);
|
|
|
+ File parentDir = localFile.getParentFile();
|
|
|
+ if (parentDir != null && !parentDir.exists()) {
|
|
|
+ parentDir.mkdirs();
|
|
|
+ }
|
|
|
+
|
|
|
+ try (OutputStream outputStream = new BufferedOutputStream(new FileOutputStream(localFile))) {
|
|
|
+ boolean success = ftpClient.retrieveFile(remotePath, outputStream);
|
|
|
+ if (success) {
|
|
|
+ logger.info("文件下载成功: {} -> {}", remotePath, localPath);
|
|
|
+ } else {
|
|
|
+ logger.error("文件下载失败: {}", remotePath);
|
|
|
+ }
|
|
|
+ return success;
|
|
|
+ } catch (IOException e) {
|
|
|
+ logger.error("文件下载异常: {}", remotePath, e);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 上传本地文件到FTP
|
|
|
+ *
|
|
|
+ * @param ftpClient FTP客户端
|
|
|
+ * @param localPath 本地文件路径
|
|
|
+ * @param remotePath 远程文件路径
|
|
|
+ * @return 是否成功
|
|
|
+ */
|
|
|
+ public static boolean uploadFile(FTPClient ftpClient, String localPath, String remotePath) {
|
|
|
+ File localFile = new File(localPath);
|
|
|
+ if (!localFile.exists() || !localFile.isFile()) {
|
|
|
+ logger.error("本地文件不存在: {}", localPath);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ try (InputStream inputStream = new BufferedInputStream(new FileInputStream(localFile))) {
|
|
|
+ String remoteDir = remotePath.substring(0, remotePath.lastIndexOf("/"));
|
|
|
+ createDirectories(ftpClient, remoteDir);
|
|
|
+
|
|
|
+ boolean success = ftpClient.storeFile(remotePath, inputStream);
|
|
|
+ if (success) {
|
|
|
+ logger.info("文件上传成功: {} -> {}", localPath, remotePath);
|
|
|
+ } else {
|
|
|
+ logger.error("文件上传失败: {}", remotePath);
|
|
|
+ }
|
|
|
+ return success;
|
|
|
+ } catch (IOException e) {
|
|
|
+ logger.error("文件上传异常: {}", remotePath, e);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 上传输入流到FTP
|
|
|
+ *
|
|
|
+ * @param ftpClient FTP客户端
|
|
|
+ * @param inputStream 输入流
|
|
|
+ * @param remotePath 远程文件路径
|
|
|
+ * @return 是否成功
|
|
|
+ */
|
|
|
+ public static boolean uploadStream(FTPClient ftpClient, InputStream inputStream, String remotePath) {
|
|
|
+ try {
|
|
|
+ String remoteDir = remotePath.substring(0, remotePath.lastIndexOf("/"));
|
|
|
+ createDirectories(ftpClient, remoteDir);
|
|
|
+
|
|
|
+ boolean success = ftpClient.storeFile(remotePath, inputStream);
|
|
|
+ if (success) {
|
|
|
+ logger.info("流上传成功: {}", remotePath);
|
|
|
+ } else {
|
|
|
+ logger.error("流上传失败: {}", remotePath);
|
|
|
+ }
|
|
|
+ return success;
|
|
|
+ } catch (IOException e) {
|
|
|
+ logger.error("流上传异常: {}", remotePath, e);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 列出目录下的文件
|
|
|
+ *
|
|
|
+ * @param ftpClient FTP客户端
|
|
|
+ * @param remotePath 远程目录路径
|
|
|
+ * @return 文件列表
|
|
|
+ */
|
|
|
+ public static List<FTPFile> listFiles(FTPClient ftpClient, String remotePath) {
|
|
|
+ List<FTPFile> fileList = new ArrayList<>();
|
|
|
+ try {
|
|
|
+ FTPFile[] files = ftpClient.listFiles(remotePath);
|
|
|
+ if (files != null) {
|
|
|
+ for (FTPFile file : files) {
|
|
|
+ fileList.add(file);
|
|
|
+ }
|
|
|
+ logger.info("列出目录文件成功: {}, 文件数: {}", remotePath, fileList.size());
|
|
|
+ }
|
|
|
+ } catch (IOException e) {
|
|
|
+ logger.error("列出目录文件异常: {}", remotePath, e);
|
|
|
+ }
|
|
|
+ return fileList;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 列出目录下指定类型的文件
|
|
|
+ *
|
|
|
+ * @param ftpClient FTP客户端
|
|
|
+ * @param remotePath 远程目录路径
|
|
|
+ * @param suffix 文件后缀(如 ".txt")
|
|
|
+ * @return 文件列表
|
|
|
+ */
|
|
|
+ public static List<FTPFile> listFilesBySuffix(FTPClient ftpClient, String remotePath, String suffix) {
|
|
|
+ List<FTPFile> fileList = new ArrayList<>();
|
|
|
+ try {
|
|
|
+ FTPFile[] files = ftpClient.listFiles(remotePath);
|
|
|
+ if (files != null) {
|
|
|
+ for (FTPFile file : files) {
|
|
|
+ if (file.isFile() && file.getName().toLowerCase().endsWith(suffix.toLowerCase())) {
|
|
|
+ fileList.add(file);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ logger.info("列出目录文件成功: {}, 匹配文件数: {}", remotePath, fileList.size());
|
|
|
+ }
|
|
|
+ } catch (IOException e) {
|
|
|
+ logger.error("列出目录文件异常: {}", remotePath, e);
|
|
|
+ }
|
|
|
+ return fileList;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 删除FTP文件
|
|
|
+ *
|
|
|
+ * @param ftpClient FTP客户端
|
|
|
+ * @param remotePath 远程文件路径
|
|
|
+ * @return 是否成功
|
|
|
+ */
|
|
|
+ public static boolean deleteFile(FTPClient ftpClient, String remotePath) {
|
|
|
+ try {
|
|
|
+ boolean success = ftpClient.deleteFile(remotePath);
|
|
|
+ if (success) {
|
|
|
+ logger.info("文件删除成功: {}", remotePath);
|
|
|
+ } else {
|
|
|
+ logger.error("文件删除失败: {}", remotePath);
|
|
|
+ }
|
|
|
+ return success;
|
|
|
+ } catch (IOException e) {
|
|
|
+ logger.error("文件删除异常: {}", remotePath, e);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 检查文件或目录是否存在
|
|
|
+ *
|
|
|
+ * @param ftpClient FTP客户端
|
|
|
+ * @param remotePath 远程路径
|
|
|
+ * @return 是否存在
|
|
|
+ */
|
|
|
+ public static boolean exists(FTPClient ftpClient, String remotePath) {
|
|
|
+ if (remotePath == null || remotePath.isEmpty()) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ FTPFile[] files = ftpClient.listFiles(remotePath);
|
|
|
+ return files != null && files.length > 0;
|
|
|
+ } catch (IOException e) {
|
|
|
+ logger.error("检查文件存在性异常: {}", remotePath, e);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 创建目录(递归创建)
|
|
|
+ *
|
|
|
+ * @param ftpClient FTP客户端
|
|
|
+ * @param remoteDir 远程目录路径
|
|
|
+ * @return 是否成功
|
|
|
+ */
|
|
|
+ public static boolean createDirectories(FTPClient ftpClient, String remoteDir) {
|
|
|
+ if (remoteDir == null || remoteDir.isEmpty()) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ String[] dirs = remoteDir.split("/");
|
|
|
+ StringBuilder currentPath = new StringBuilder();
|
|
|
+
|
|
|
+ for (String dir : dirs) {
|
|
|
+ if (dir == null || dir.isEmpty()) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ currentPath.append("/").append(dir);
|
|
|
+
|
|
|
+ if (!exists(ftpClient, currentPath.toString())) {
|
|
|
+ boolean success = ftpClient.makeDirectory(currentPath.toString());
|
|
|
+ if (!success) {
|
|
|
+ logger.warn("创建目录失败: {}", currentPath);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ } catch (IOException e) {
|
|
|
+ logger.error("创建目录异常: {}", remoteDir, e);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 切换工作目录
|
|
|
+ *
|
|
|
+ * @param ftpClient FTP客户端
|
|
|
+ * @param remotePath 远程目录路径
|
|
|
+ * @return 是否成功
|
|
|
+ */
|
|
|
+ public static boolean changeWorkingDirectory(FTPClient ftpClient, String remotePath) {
|
|
|
+ try {
|
|
|
+ boolean success = ftpClient.changeWorkingDirectory(remotePath);
|
|
|
+ if (success) {
|
|
|
+ logger.info("切换工作目录成功: {}", remotePath);
|
|
|
+ } else {
|
|
|
+ logger.error("切换工作目录失败: {}", remotePath);
|
|
|
+ }
|
|
|
+ return success;
|
|
|
+ } catch (IOException e) {
|
|
|
+ logger.error("切换工作目录异常: {}", remotePath, e);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取文件大小
|
|
|
+ *
|
|
|
+ * @param ftpClient FTP客户端
|
|
|
+ * @param remotePath 远程文件路径
|
|
|
+ * @return 文件大小(字节)
|
|
|
+ */
|
|
|
+ public static long getFileSize(FTPClient ftpClient, String remotePath) {
|
|
|
+ try {
|
|
|
+ FTPFile[] files = ftpClient.listFiles(remotePath);
|
|
|
+ if (files != null && files.length > 0) {
|
|
|
+ return files[0].getSize();
|
|
|
+ }
|
|
|
+ } catch (IOException e) {
|
|
|
+ logger.error("获取文件大小异常: {}", remotePath, e);
|
|
|
+ }
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+}
|