1.引入依赖

  1. # 1.pom文件引入依赖
  2. <!--引入ftp的工具-->
  3. <dependency>
  4. <groupId>commons-net</groupId>
  5. <artifactId>commons-net</artifactId>
  6. <version>3.7.2</version>
  7. </dependency>
  8. # 2.applicaiton.yml的配置中添加
  9. ftps:
  10. connection:
  11. server: 172.22.1.242
  12. port: 10012
  13. username: ftpuser
  14. password: ftp123.,

2.工具类

  1. import cn.hutool.core.io.FileUtil;
  2. import cn.hutool.core.io.IoUtil;
  3. import com.qif.dsa.common.constant.StringConstant;
  4. import lombok.extern.slf4j.Slf4j;
  5. import org.apache.commons.compress.utils.IOUtils;
  6. import org.apache.commons.compress.utils.Lists;
  7. import org.apache.commons.lang3.StringUtils;
  8. import org.apache.commons.net.ftp.*;
  9. import org.springframework.beans.factory.annotation.Value;
  10. import org.springframework.stereotype.Component;
  11. import java.io.*;
  12. import java.nio.charset.StandardCharsets;
  13. import java.util.List;
  14. @Slf4j
  15. @Component
  16. public class FtpUtil {
  17. private FTPSClient ftpsClient = null;
  18. @Value(value = "${ftps.connection.server}")
  19. private String server;
  20. @Value(value = "${ftps.connection.port}")
  21. private int port;
  22. @Value(value = "${ftps.connection.username}")
  23. private String username;
  24. @Value(value = "${ftps.connection.password}")
  25. private String password;
  26. /**
  27. * 链接到服务器
  28. *
  29. * @return boolean
  30. */
  31. public boolean connect() {
  32. if (ftpsClient != null && ftpsClient.isConnected()) {
  33. return true;
  34. }
  35. try {
  36. ftpsClient = new FTPSClient("SSL", true);
  37. ftpsClient.setAuthValue("SSL");
  38. ftpsClient.setEnabledSessionCreation(true);
  39. ftpsClient.connect(this.server, this.port);
  40. ftpsClient.pasv();
  41. ftpsClient.login(this.username, this.password);
  42. ftpsClient.enterLocalPassiveMode();
  43. ftpsClient.setUseEPSVwithIPv4(true);
  44. ftpsClient.execAUTH("SSL");
  45. ftpsClient.execPBSZ(0);
  46. ftpsClient.execPROT("P");
  47. // 检测连接是否成功
  48. int reply = ftpsClient.getReplyCode();
  49. if (!FTPReply.isPositiveCompletion(reply)) {
  50. this.close();
  51. }
  52. // 设置上传模式binary or ascii
  53. ftpsClient.setFileType(FTP.BINARY_FILE_TYPE);
  54. return true;
  55. } catch (Exception ex) {
  56. ex.printStackTrace();
  57. // 关闭
  58. this.close();
  59. return false;
  60. }
  61. }
  62. private boolean cd(String dir) throws IOException {
  63. return ftpsClient.changeWorkingDirectory(dir);
  64. }
  65. /**
  66. * 获取目录下所有的文件名称
  67. *
  68. * @param filePath 路径
  69. * @return FTPFile
  70. * @throws IOException
  71. */
  72. private FTPFile[] getFileList(String filePath) throws IOException {
  73. return ftpsClient.listFiles(filePath);
  74. }
  75. /**
  76. * 循环将设置工作目录
  77. *
  78. * @param ftpPath 文件路径
  79. * @return boolean
  80. * @author xu wen kai
  81. * @create: 2021/3/31 18:49
  82. */
  83. public boolean changeDir(String ftpPath) {
  84. if (!ftpsClient.isConnected()) {
  85. return false;
  86. }
  87. try {
  88. // 将路径中的斜杠统一
  89. char[] chars = ftpPath.toCharArray();
  90. StringBuffer sbStr = new StringBuffer(256);
  91. for (char aChar : chars) {
  92. if ('\\' == aChar) {
  93. sbStr.append(StringConstant.SLASH);
  94. } else {
  95. sbStr.append(aChar);
  96. }
  97. }
  98. ftpPath = sbStr.toString();
  99. if (!ftpPath.contains(StringConstant.SLASH)) {
  100. // 只有一层目录
  101. ftpsClient.changeWorkingDirectory(new String(ftpPath.getBytes(), StandardCharsets.UTF_8));
  102. } else {
  103. // 多层目录循环创建
  104. String[] paths = ftpPath.split(StringConstant.SLASH);
  105. for (int i = 0; i < paths.length; i++) {
  106. ftpsClient.changeWorkingDirectory(new String(paths[i].getBytes(), StandardCharsets.UTF_8));
  107. }
  108. }
  109. return true;
  110. } catch (Exception e) {
  111. return false;
  112. }
  113. }
  114. /**
  115. * 循环创建目录,并且创建完目录后,设置工作目录为当前创建的目录下
  116. */
  117. public boolean mkDir(String ftpPath) {
  118. if (!ftpsClient.isConnected()) {
  119. return false;
  120. }
  121. try {
  122. // 将路径中的斜杠统一
  123. char[] chars = ftpPath.toCharArray();
  124. StringBuffer sbStr = new StringBuffer(256);
  125. for (char aChar : chars) {
  126. if ('\\' == aChar) {
  127. sbStr.append('/');
  128. } else {
  129. sbStr.append(aChar);
  130. }
  131. }
  132. ftpPath = sbStr.toString();
  133. if (!ftpPath.contains(StringConstant.SLASH)) {
  134. // 只有一层目录
  135. ftpsClient.makeDirectory(new String(ftpPath.getBytes(), StandardCharsets.UTF_8));
  136. ftpsClient.changeWorkingDirectory(new String(ftpPath.getBytes(), StandardCharsets.UTF_8));
  137. } else {
  138. // 多层目录循环创建
  139. String[] paths = ftpPath.split(StringConstant.SLASH);
  140. for (String path : paths) {
  141. ftpsClient.makeDirectory(new String(path.getBytes(), StandardCharsets.UTF_8));
  142. ftpsClient.changeWorkingDirectory(new String(path.getBytes(), StandardCharsets.UTF_8));
  143. }
  144. }
  145. return true;
  146. } catch (Exception e) {
  147. return false;
  148. }
  149. }
  150. /**
  151. * 上传文件到FTP服务器
  152. *
  153. * @param localDirectoryAndFileName 本地文件目录和文件名
  154. * @param ftpFileName 上传后的文件名
  155. * @param ftpDirectory FTP目录如:/path1/path2/,如果目录不存在回自动创建目录
  156. */
  157. public boolean put(String localDirectoryAndFileName, String ftpFileName, String ftpDirectory) {
  158. if (!ftpsClient.isConnected()) {
  159. return false;
  160. }
  161. boolean flag = false;
  162. if (ftpsClient != null) {
  163. File srcFile = new File(localDirectoryAndFileName);
  164. FileInputStream fis = null;
  165. try {
  166. fis = new FileInputStream(srcFile);
  167. // 创建目录
  168. this.mkDir(ftpDirectory);
  169. ftpsClient.setBufferSize(1024);
  170. ftpsClient.setControlEncoding("UTF-8");
  171. // 设置文件类型(二进制)
  172. ftpsClient.setFileType(FTPClient.BINARY_FILE_TYPE);
  173. // 上传
  174. flag = ftpsClient.storeFile(new String(ftpFileName.getBytes(), StandardCharsets.UTF_8), fis);
  175. } catch (Exception e) {
  176. this.close();
  177. return false;
  178. } finally {
  179. IOUtils.closeQuietly(fis);
  180. }
  181. }
  182. return flag;
  183. }
  184. public boolean uploadFile(InputStream inputStream, String ftpFileName, String ftpDirectory) {
  185. this.connect();
  186. if (!ftpsClient.isConnected()) {
  187. return false;
  188. }
  189. boolean flag = false;
  190. if (ftpsClient != null) {
  191. try {
  192. // 创建目录
  193. this.mkDir(ftpDirectory);
  194. ftpsClient.setBufferSize(1024);
  195. ftpsClient.setControlEncoding("UTF-8");
  196. // 设置文件类型(二进制)
  197. ftpsClient.setFileType(FTPClient.BINARY_FILE_TYPE);
  198. // 上传
  199. flag = ftpsClient.storeFile(new String(ftpFileName.getBytes(), StandardCharsets.UTF_8), inputStream);
  200. } catch (Exception e) {
  201. this.close();
  202. return false;
  203. } finally {
  204. this.close();
  205. IOUtils.closeQuietly(inputStream);
  206. }
  207. }
  208. return flag;
  209. }
  210. /**
  211. * 复制ftp的文件到指定目录下,service与ftps在同一个服务器时使用
  212. *
  213. * @param srcFile
  214. * @param targetFile
  215. */
  216. public void getFile(String srcFile, String targetFile) {
  217. this.connect();
  218. if (!ftpsClient.isConnected()) {
  219. log.info("===>> ftps service is not connected ...");
  220. return;
  221. }
  222. if (StringUtils.isEmpty(srcFile)) {
  223. log.info("===>> FTP路径不存在.");
  224. return;
  225. }
  226. if (StringUtils.isEmpty(targetFile)) {
  227. log.info("===>> 目标路径不存在.");
  228. return;
  229. }
  230. InputStream ins = null;
  231. try {
  232. log.info("===>> start copy ftps file");
  233. ins = ftpsClient.retrieveFileStream(srcFile);
  234. if (ins == null) {
  235. log.info("源文件未上传.file:{}", srcFile);
  236. return;
  237. }
  238. IOUtils.copy(ins, new FileOutputStream(new File(targetFile)));
  239. log.info("===>> copy ftps file end");
  240. } catch (Exception e) {
  241. log.info("===>> download {} error: {}", srcFile, e);
  242. e.printStackTrace();
  243. } finally {
  244. IoUtil.close(ins);
  245. }
  246. }
  247. /**
  248. * 从FTP服务器上下载文件并返回下载文件长度
  249. *
  250. * @param ftpFullName 路径加文件名称
  251. * @param localFullName 本地路径名称
  252. * @return long
  253. */
  254. public long downLoadFileToLocal(String ftpFullName, String localFullName) {
  255. this.connect();
  256. long result = 0;
  257. if (!ftpsClient.isConnected()) {
  258. return result;
  259. }
  260. if (StringUtils.isEmpty(ftpFullName)) {
  261. log.info("FTP路径不存在.");
  262. return result;
  263. }
  264. if (StringUtils.isEmpty(localFullName)) {
  265. log.info("本地路径不存在.");
  266. return result;
  267. }
  268. ftpsClient.enterLocalPassiveMode();
  269. // 将路径中的斜杠统一
  270. char[] chars = ftpFullName.toCharArray();
  271. StringBuilder sbStr = new StringBuilder(256);
  272. for (char aChar : chars) {
  273. if ('\\' == aChar) {
  274. sbStr.append('/');
  275. } else {
  276. sbStr.append(aChar);
  277. }
  278. }
  279. String ftpFileName = sbStr.toString();
  280. String filePath = ftpFileName.substring(0, ftpFileName.lastIndexOf(StringConstant.SLASH));
  281. String fileName = ftpFileName.substring(ftpFileName.lastIndexOf(StringConstant.SLASH) + 1);
  282. this.changeDir(filePath);
  283. String localDirectory = localFullName.substring(0, localFullName.lastIndexOf(StringConstant.SLASH));
  284. try (InputStream ins = ftpsClient.retrieveFileStream(new String(fileName.getBytes(), StandardCharsets.UTF_8))) {
  285. log.info("===>> start download file[{}],[{}]", ftpFileName, fileName);
  286. if (ins == null) {
  287. log.info("===>> 未读取到文件或者文件内容为空");
  288. return result;
  289. }
  290. File file = new File(localDirectory);
  291. if (!file.isDirectory() || !file.exists()) {
  292. log.info("===>> file path not exist and created");
  293. if (!file.mkdirs()) {
  294. FileUtil.mkdir(file);
  295. }
  296. }
  297. this.changeDir(filePath);
  298. if (IOUtils.copy(ins, new FileOutputStream(localFullName)) <= 0) {
  299. log.info("===>> 文件下载失败");
  300. }
  301. log.info("===>> download file from ftps end");
  302. return 1;
  303. } catch (IOException e) {
  304. e.printStackTrace();
  305. }
  306. return result;
  307. }
  308. /**
  309. * 从ftp上下载 指定目录下的 指定文件
  310. * @param path -- 文件的保存路径
  311. * @param filename -- 文件名称
  312. * @return
  313. */
  314. public InputStream downLoadFile(String path, String filename) {
  315. this.connect();
  316. InputStream inputStream = null;
  317. ByteArrayOutputStream bos = new ByteArrayOutputStream();
  318. try {
  319. ftpsClient.changeWorkingDirectory(path);
  320. inputStream = ftpsClient.retrieveFileStream(filename);
  321. if (inputStream == null) {
  322. log.info("FTPS服务不存在该文件.path:{},filename:{}", path, filename);
  323. return null;
  324. }
  325. byte[] receiveBuffer = new byte[2048];
  326. int readBytesSize = inputStream.read(receiveBuffer);
  327. while (readBytesSize != -1) {
  328. bos.write(receiveBuffer, 0, readBytesSize);
  329. readBytesSize = inputStream.read(receiveBuffer);
  330. }
  331. } catch (IOException e) {
  332. log.error("切换目录失败。path:{},errMsg:{}", path, e);
  333. } finally {
  334. try {
  335. IoUtil.close(inputStream);
  336. if (inputStream != null) {
  337. ftpsClient.completePendingCommand();
  338. }
  339. IoUtil.close(bos);
  340. ftpsClient.disconnect();
  341. } catch (IOException e) {
  342. log.error("获取FTP文件失败.path:{},errMsg:{}", path, e);
  343. }
  344. }
  345. return new ByteArrayInputStream(bos.toByteArray());
  346. }
  347. /**
  348. * 将远程的文件,保存到本地文件
  349. * @param remoteFilePath --远程文件名称
  350. * @param localFilePath -- 本地目录明湖曾
  351. * @param fileName -- 文件名称
  352. * @return
  353. */
  354. public boolean downloadFile(String remoteFilePath, String localFilePath, String fileName) {
  355. this.connect();
  356. boolean flag = false;
  357. try {
  358. ftpsClient.changeWorkingDirectory(remoteFilePath);
  359. FTPFile[] fs = ftpsClient.listFiles();
  360. for (FTPFile ff : fs) {
  361. if (ff.getName().equals(fileName)) {
  362. File localFile = new File(localFilePath + File.separator + fileName);
  363. OutputStream is = new FileOutputStream(localFile);
  364. ftpsClient.retrieveFile(ff.getName(), is);
  365. is.close();
  366. flag = true;
  367. }
  368. }
  369. } catch (Exception e) {
  370. e.printStackTrace();
  371. }
  372. return flag;
  373. }
  374. /**
  375. * 返回FTP目录下的文件列表
  376. *
  377. * @param ftpDirectory 路径
  378. * @return List<String>
  379. */
  380. public List<String> getFileNameList(String ftpDirectory) {
  381. this.connect();
  382. List<String> list = Lists.newArrayList();
  383. if (!connect()) {
  384. return list;
  385. }
  386. try {
  387. DataInputStream dis = new DataInputStream(ftpsClient.retrieveFileStream(ftpDirectory));
  388. String filename;
  389. while ((filename = dis.readLine()) != null) {
  390. list.add(filename);
  391. }
  392. } catch (Exception e) {
  393. e.printStackTrace();
  394. }
  395. return list;
  396. }
  397. /**
  398. * 删除FTP上的文件
  399. *
  400. * @param ftpDirAndFileName 路径名称
  401. */
  402. public boolean deleteFile(String ftpDirAndFileName) {
  403. return ftpsClient.isConnected();
  404. }
  405. /**
  406. * 删除FTP目录
  407. *
  408. * @param ftpDirectory 路径
  409. */
  410. public boolean deleteDirectory(String ftpDirectory) {
  411. return ftpsClient.isConnected();
  412. }
  413. /**
  414. * 关闭链接
  415. */
  416. public void close() {
  417. try {
  418. if (ftpsClient != null && ftpsClient.isConnected()) {
  419. ftpsClient.disconnect();
  420. }
  421. } catch (Exception e) {
  422. e.printStackTrace();
  423. }
  424. }
  425. public FTPSClient getFtpsClient() {
  426. return ftpsClient;
  427. }
  428. public void setFtpsClient(FTPSClient ftpsClient) {
  429. this.ftpsClient = ftpsClient;
  430. }
  431. }