依赖

  1. <dependency>
  2. <groupId>commons-net</groupId>
  3. <artifactId>commons-net</artifactId>
  4. <version>3.4</version>
  5. </dependency>
  6. <dependency>
  7. <groupId>org.apache.commons</groupId>
  8. <artifactId>commons-lang3</artifactId>
  9. <version>3.3.2</version>
  10. </dependency>
  11. <dependency>
  12. <groupId>org.apache.ant</groupId>
  13. <artifactId>ant</artifactId>
  14. <version>1.10.5</version>
  15. </dependency>

可选择多个路径进行压缩

依赖

  1. <dependency>
  2. <groupId>org.apache.ant</groupId>
  3. <artifactId>ant</artifactId>
  4. <version>1.10.5</version>
  5. </dependency>

可选择多个路径进行压缩

依赖

  1. <dependency>
  2. <groupId>org.apache.ant</groupId>
  3. <artifactId>ant</artifactId>
  4. <version>1.10.5</version>
  5. </dependency>

可选择多个路径进行压缩

  1. package per.qiao.utils.ftp;
  2. import org.apache.commons.net.ftp.FTPClient;
  3. import org.apache.commons.net.ftp.FTPClientConfig;
  4. import org.apache.commons.net.ftp.FTPFile;
  5. import org.apache.commons.net.ftp.FTPReply;
  6. import org.apache.tools.zip.ZipEntry;
  7. import org.apache.tools.zip.ZipOutputStream;
  8. import org.slf4j.Logger;
  9. import org.slf4j.LoggerFactory;
  10. import java.io.File;
  11. import java.io.IOException;
  12. import java.io.InputStream;
  13. /**
  14. * Create by IntelliJ Idea 2018.2
  15. *
  16. * @author: qyp
  17. * Date: 2019-07-19 17:10
  18. */
  19. public class FtpFileZipUtls {
  20. private final static Logger logger = LoggerFactory.getLogger(FtpFileZipUtls.class);
  21. /**
  22. * 加载一个非空文件夹
  23. */
  24. private static void loadFile(FTPClient ftp, String dirPath, ZipOutputStream zos) throws IOException {
  25. FTPFile[] ftpFiles = ftp.listFiles();
  26. // length小于0用于区分非空文件夹与空文件夹和文件的区别
  27. // 退到上层再进入
  28. if (ftpFiles.length <= 0 && ftp.changeToParentDirectory()) {
  29. logger.info("退回到: " + ftp.printWorkingDirectory());
  30. dirPath = dirPath.replaceAll("\\\\", "/");
  31. boolean b = ftp.changeWorkingDirectory(getFileName(dirPath.substring(dirPath.lastIndexOf("/") + 1)));
  32. logger.info("进入: " + ftp.printWorkingDirectory());
  33. // 是一个空文件夹
  34. if (b && (ftpFiles == null || ftpFiles.length <= 0)) {
  35. zos.putNextEntry(new ZipEntry(getFileName(dirPath) + File.separator));
  36. return;
  37. }
  38. }
  39. for (FTPFile f : ftpFiles) {
  40. if (f.isFile()) {
  41. InputStream in = ftp.retrieveFileStream(f.getName());
  42. zos.putNextEntry(new ZipEntry(getFileName(dirPath) + File.separator + f.getName()));
  43. addToZOS(in, zos);
  44. ftp.completePendingCommand();
  45. } else {
  46. if (ftp.changeWorkingDirectory(f.getName())) {
  47. loadFile(ftp, dirPath + File.separator + f.getName(), zos);
  48. // ftp指针移动到上一层
  49. ftp.changeToParentDirectory();
  50. }
  51. }
  52. }
  53. }
  54. /**
  55. * 将文件夹中的 .替换为^^
  56. * @param sb
  57. * @return
  58. */
  59. private static void replaceFileName(StringBuilder sb, String onepath) {
  60. sb.replace(sb.indexOf(onepath), sb.indexOf(onepath) + onepath.length(), onepath.replaceAll("\\.", "^^"));
  61. }
  62. /**
  63. * 将文件夹路径中的 ^^ 替换成 .
  64. * @param sb
  65. * @return
  66. */
  67. private static String getFileName(String sb) {
  68. StringBuilder result = new StringBuilder(sb);
  69. while (result.indexOf("^^") > -1) {
  70. result.replace(result.indexOf("^^"), result.indexOf("^^") + 2, ".");
  71. }
  72. return result.toString();
  73. }
  74. /**
  75. * 切换目录 返回切换的层级数
  76. * @param sb
  77. * @param ftp
  78. * @return 切换的层级数
  79. * @throws IOException
  80. */
  81. private static int exchageDir(StringBuilder sb, FTPClient ftp) throws IOException {
  82. // 计入进入的文件夹的次数,方便回退
  83. int level = 0;
  84. String[] pathes = sb.toString().split("/");
  85. for (int i = 0, len = pathes.length; i < len; i++) {
  86. String onepath = pathes[i];
  87. if (onepath == null || "".equals(onepath.trim())) {
  88. continue;
  89. }
  90. //文件排除
  91. boolean flagDir = ftp.changeWorkingDirectory(onepath);
  92. if (flagDir) {
  93. level++;
  94. if (onepath.contains(".")) {
  95. //把文件夹中的.用^^代替
  96. replaceFileName(sb, onepath);
  97. }
  98. logger.info("成功连接ftp目录:" + ftp.printWorkingDirectory());
  99. } else {
  100. logger.warn("连接ftp目录失败:" + ftp.printWorkingDirectory());
  101. }
  102. }
  103. return level;
  104. }
  105. /**
  106. * 处理单个文件和空文件夹的情况 处理了返回true 未处理返回false
  107. * 注意:这里是指数组中给的路径直接是文件或者空文件夹的情况
  108. * @param ftp
  109. * @param path 需要压缩的文件(文件夹)路径(相对根)
  110. * @param zos
  111. * @return
  112. * @throws IOException
  113. */
  114. public static boolean delFile(FTPClient ftp, StringBuilder path, ZipOutputStream zos) throws IOException {
  115. int times = exchageDir(path, ftp);
  116. String fileRelativePaht = path.toString();
  117. String[] split = fileRelativePaht.split("/");
  118. // 是否处理过
  119. boolean isDel = false;
  120. //有父级目录
  121. if (split != null && split.length > 0) {
  122. String lastSegmeng = split[split.length - 1];
  123. //path直接是文件
  124. if (split[split.length - 1].contains(".")) {
  125. zos.putNextEntry(new ZipEntry(fileRelativePaht));
  126. addToZOS(ftp.retrieveFileStream(lastSegmeng), zos);
  127. ftp.completePendingCommand();
  128. isDel = true;
  129. } else if (ftp.listFiles().length <= 0) {
  130. // 空文件夹
  131. zos.putNextEntry(new ZipEntry(fileRelativePaht + File.separator));
  132. isDel = true;
  133. }
  134. // 如果被处理过(空文件夹或者直接给的文件的路径),退回到根路径(以免污染下次循环的ftp指针)
  135. if (isDel) {
  136. for (int i = 0; i < times; i++) {
  137. ftp.changeToParentDirectory();
  138. }
  139. }
  140. }
  141. return isDel;
  142. }
  143. /**
  144. * 添加文件到压缩流
  145. * @param in 输入流(一般就直接是从FTP中获取的)
  146. * @param zos 压缩输出流
  147. * @throws IOException
  148. */
  149. public static void addToZOS(InputStream in, ZipOutputStream zos) throws IOException {
  150. byte[] buf = new byte[1024];
  151. //BufferedOutputStream bzos = new BufferedOutputStream(zos);
  152. try {
  153. for (int len; (len = (in.read(buf))) != -1; ) {
  154. zos.write(buf, 0 , len);
  155. }
  156. } catch (IOException e) {
  157. System.out.println("流转换异常");
  158. throw e;
  159. } finally {
  160. if (in != null) {
  161. try {
  162. in.close();
  163. } catch (IOException e) {
  164. System.out.println("关流异常");
  165. e.printStackTrace();
  166. }
  167. }
  168. }
  169. }
  170. public static FTPClient getFtpClient(String path) throws Exception {
  171. String server = "127.0.0.1";
  172. int port = 21;
  173. String username = "test";
  174. String password = "test";
  175. // path = "/FTPStation/";
  176. FTPClient ftpClient = connectServer(server, port, username, password, path);
  177. return ftpClient;
  178. }
  179. /**
  180. *
  181. * @param server
  182. * @param port
  183. * @param username
  184. * @param password
  185. * @param path 连接的节点(相对根路径的文件夹)
  186. * @return
  187. */
  188. public static FTPClient connectServer(String server, int port, String username, String password, String path) throws IOException {
  189. path = path == null ? "" : path;
  190. FTPClient ftp = new FTPClient();
  191. //下面四行代码必须要,而且不能改变编码格式,否则不能正确下载中文文件
  192. // 如果使用serv-u发布ftp站点,则需要勾掉“高级选项”中的“对所有已收发的路径和文件名使用UTF-8编码”
  193. ftp.setControlEncoding("GBK");
  194. FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_NT);
  195. conf.setServerLanguageCode("zh");
  196. ftp.configure(conf);
  197. // 判断ftp是否存在
  198. ftp.connect(server, port);
  199. ftp.setDataTimeout(2 * 60 * 1000);
  200. if (!FTPReply.isPositiveCompletion(ftp.getReplyCode())) {
  201. ftp.disconnect();
  202. System.out.println(server + "拒绝连接");
  203. }
  204. //登陆ftp
  205. boolean login = ftp.login(username, password);
  206. if (logger.isDebugEnabled()) {
  207. if (login) {
  208. logger.debug("登陆FTP成功! ip: " + server);
  209. } else {
  210. logger.debug("登陆FTP失败! ip: " + server);
  211. }
  212. }
  213. //根据输入的路径,切换工作目录。这样ftp端的路径就可以使用相对路径了
  214. exchageDir(new StringBuilder(path), ftp);
  215. return ftp;
  216. }
  217. public static void main(String[] args) throws Exception {
  218. String[] paths = {"/CAD/你好.txt", "/CAD/1.第一层"};
  219. String savePath = "e:/temp/zz.zip";
  220. //连接到的节点
  221. String rootDir = "/CAD";
  222. FTPClient ftp = getFtpClient(rootDir);
  223. zipFileByPaths(ftp, savePath, paths);
  224. }
  225. /**
  226. * 多FTP路径压缩
  227. * @param ftp
  228. * @param savePath
  229. * @param filePaths
  230. * @throws Exception
  231. */
  232. public static void zipFileByPaths(FTPClient ftp, String savePath, String[] filePaths) throws Exception {
  233. try (ZipOutputStream zos = ZipUtils.getOutPutStream(savePath)) {
  234. for (String path : filePaths) {
  235. StringBuilder sb = new StringBuilder(path);
  236. //delFile时进入的文件夹的路径(当前需要遍历的文件的路径)
  237. String before = ftp.printWorkingDirectory();
  238. if (delFile(ftp, sb, zos)) {
  239. continue;
  240. }
  241. loadFile(ftp, sb.toString(), zos);
  242. // 文件加载完毕后,需要将ftp的指针退到开始状态
  243. String after = ftp.printWorkingDirectory();
  244. backPath(before, after, ftp);
  245. }
  246. zos.flush();
  247. } catch (Exception e) {
  248. logger.error("多路径文件压缩失败");
  249. e.printStackTrace();
  250. throw e;
  251. }
  252. }
  253. /**
  254. * ftp 指针回退
  255. * @param end
  256. * @param start
  257. * @param ftp
  258. * @throws IOException
  259. */
  260. private static void backPath(String end, String start, FTPClient ftp) throws IOException {
  261. long startTime = System.currentTimeMillis();
  262. do {
  263. if (!end.equals(start) && ftp.changeToParentDirectory()) {
  264. start = ftp.printWorkingDirectory();
  265. }
  266. // 防止意外出现空循环 30s等待时间
  267. if (System.currentTimeMillis() - startTime > 30 * 1000) {
  268. break;
  269. }
  270. } while (!end.equals(start));
  271. }
  272. }

从ftp获取文件并生成压缩包的更多相关文章

  1. Poco之ftp获取文件列表以及下载文件

    #include <iostream>#include <string>#include <vector>#include <algorithm>#in ...

  2. ftpget 从Windows FTP服务端获取文件

    /********************************************************************************* * ftpget 从Windows ...

  3. C#WPF做FTP上传下载获取文件列表

    Xaml.cs: using Microsoft.Win32;using System;using System.Collections.Generic;using System.IO;using S ...

  4. 使用.net FtpWebRequest 实现FTP常用功能 上传 下载 获取文件列表 移动 切换目录 改名 .

    平时根本没时间搞FTP什么的,现在这个项目需要搞FTP,为什么呢,我给大家说下项目背景,我们的一个应用程序上需要上传图片,但是用户部署程序的服务器上不让上传任何东西,给了我们一个FTP账号和密码,让我 ...

  5. SSIS 实例 从Ftp获取多个文件并对数据库进行增量更新。

    整个流程 Step 1 放置一个FTP Task 将远程文件复制到本地 建立FTP链接管理器后 Is LocalPatchVariable 设置为Ture 并创建一个变量设置本地路径 Operatio ...

  6. FTP文件操作之获取文件列表

    前面已经介绍了很多关于FTP对文件的操作,今天再跟大家介绍一个获取文件列表的功能.这个功能应该算是最简单的一个了,它只是获取了一下文件信息,而没有进行实质上的数据传输. 下面是是该功能的核心代码:   ...

  7. C# FTP操作类(获取文件和文件夹列表)

    一.如何获取某一目录下的文件和文件夹列表. 由于FtpWebRequest类只提供了WebRequestMethods.Ftp.ListDirectory方式和WebRequestMethods.Ft ...

  8. ftp获取远程Pdf文件

    此程序需要安装ftp服务器,安装adobe reader(我这里使用的adobe reader9.0) 1.部署ftp服务器 将ftp的权限设置为允许匿名访问,部署完成 2.安装adobe reade ...

  9. java版ftp简易客户端(可以获取文件的名称及文件大小)

    java版ftp简易客户端(可以获取文件的名称及文件大小) package com.ccb.ftp; import java.io.IOException; import java.net.Socke ...

随机推荐

  1. python 输出‘\xe8\xb4\x9d\xe8\xb4\x9d’, ‘\xe6\x99\xb6\xe6\x99\xb6’, ‘\xe6\xac\xa2\xe6\xac\xa2’]

    如上代码块,结果输出为: [‘\xe8\xb4\x9d\xe8\xb4\x9d’, ‘\xe6\x99\xb6\xe6\x99\xb6’, ‘\xe6\xac\xa2\xe6\xac\xa2’] 北京 ...

  2. Linux内核TCP MSS机制详细分析

    前言 上周Linux内核修复了4个CVE漏洞[1],其中的CVE-2019-11477感觉是一个很厉害的Dos漏洞,不过因为有其他事打断,所以进展的速度比较慢,这期间网上已经有相关的分析文章了.[2] ...

  3. Java上传视频(mencoder)

    页面: 上传文件时的关键词:enctype="multipart/form-data" <%@ page language="java" import=& ...

  4. 微信小程序不同机型的兼容布局解决

    因为小程序是以微信为平台运行的,可以同时运行在android与ios的设备上,所以不可避免的会遇到布局适配问题,特别是在iphone5上,因为屏幕尺寸小的缘故,也是适配问题最多的机型,下面就简单介绍几 ...

  5. git只提交修改部分的代码

    思路: 先用git status 查找出哪些文件被修改过了,然后 只git commit odin/code/pom.xml 1. $ git status (查看当前更改的代码) On branch ...

  6. input标签在谷歌浏览器记住密码的自动填充问题

    //使用autocomplete="new-password" <Input type='password' autocomplete="new-password& ...

  7. Linux openkvm disk expansion

    How to Increase the size of a Linux LVM by expanding the virtual machine disk https://www.rootusers. ...

  8. layui的select下拉框太长被遮挡了的解决办法

    layui的select下拉框太长采用滚动条的形式出现,可以给select的dl加一个最大高度,具体的效果如下图 .layui-form-select dl { max-height:160px; }

  9. flutter Checkbox 复选框组件

    import 'package:flutter/material.dart'; class CheckboxDemo extends StatefulWidget { @override _Check ...

  10. 16个python常用魔法函数

    ==,is的使用 ·is是比较两个引用是否指向了同一个对象(引用比较). ·==是比较两个对象是否相等 1.__ init__(): 所有类的超类object,有一个默认包含pass的__ init ...