踩坑之《FTPClient.listFiles()不能获取文件》

打印 上一主题 下一主题

主题 872|帖子 872|积分 2616

在做一件什么事情

当时做在做一个文件上传下载的功能,其中涉及到的是存储FTP服务器。这个系统是某司的内部系统,我们在七楼开发调试,完是到三楼部署。
遇到了什么问题

当时就遇到了一个很奇怪的问题。问题现象是获取列表的时候,返回数据为空,偶然候还会提示链接断开。这个问题坑的我和向导楼上楼下跑了七八趟。
  1. ftpUtilsInst.list(path);
复制代码
问题分析

连接断开容易办理,断开了为重新连接就可以了。
一开始猜想是应该有个参数可以配置对应的连接时间,效果发现还真有。
  1.    /**
  2.      * Sets the connection timeout in milliseconds, which will be passed to the {@link Socket} object's
  3.      * connect() method.
  4.      * @param connectTimeout The connection timeout to use (in ms)
  5.      * @since 2.0
  6.      */
  7.     public void setConnectTimeout(int connectTimeout) {
  8.         this.connectTimeout = connectTimeout;
  9.     }
复制代码
但是问题还是没有办理,就算是这个时间你设置的很长,最终还是有断开连接的一天。
那我们就自己封装一层,每次使用的使用重新建立连接⬇︎⬇︎⬇︎⬇
  1. public FTPFile[] list(String path) throws IOException {
  2.         FTPFile[] listFiles = null;
  3.         try {
  4.             listFiles = ftpUtilsInst.list(path);
  5.         } catch (FTPConnectionClosedException e) {
  6.             logger.error("ftp closed: {}", e);
  7.             if (ftpUtilsInst.connect()) {
  8.                 listFiles = ftpUtilsInst.list(path);
  9.             } else {
  10.                 throw e;
  11.             }
  12.         }
  13.         return listFiles;
  14.     }
复制代码
这样就把连接断开的问题办理了
目录下面有数据,但返回列表为空

原因是由于FTP有两种工作模式。一种是自动模式,一种是被动模式。

  • 自动模式传输过程
    1.当客户端须要从 FTP 服务器下载文件大概上传文件时,首先会与 FTP 服务器建立一个控制连接。这个控制连接是由客户端发起的,通过 TCP 协议连接到 FTP 服务器的 21 端口。
    2.客户端在控制连接上发送 PORT 命令给服务器。这个命令包含了客户端用于吸收数据的 IP 地址和端口号。例如,客户端告诉服务器自己的 IP 地址是 192.168.1.10,而且数据吸收端口是 1025(这个端口号通常是大于 1024 的临时端口)
    3.服务器收到 PORT 命令后,会使用 20 端口自动向客户端指定的 IP 地址和端口号发起一个数据连接,用于传输文件数据。
    自动的优点是:
    从服务器的角度来看,自动模式相对简朴,由于服务器只须要按照标准流程,使用 20 端口自动连接客户端即可。
    自动的缺点是:
    在一些网络环境下可能会出现问题。例如,如果客户端位于防火墙大概 NAT(网络地址转换)设备后面,防火墙可能会阻止来自外部服务器的自动连接哀求。由于防火墙通常会默认阻止外部主机自动向内部网络的主机发起连接,除非进行特殊的配置。
  • 被动模式传输过程
    1.客户端先与 FTP 服务器建立控制连接,通过 TCP 协议连接到服务器的 21 端口。
    2.客户端发送 PASV 命令给服务器,哀求服务器进入被动模式。
    3.服务器收到 PASV 命令后,会分配一个临时的端口号(大于 1024),并将自己的 IP 地址和这个临时端口号通过控制连接返回给客户端。例如,服务器返回的信息可能是(192.168.2.20,1026),表示服务器的数据连接端口是 1026。
    4.客户端收到服务器返回的 IP 地址和端口号后,自动向服务器的这个端口发起数据连接,从而建立用于文件传输的数据通道。
    被动优点:
    对于位于防火墙或 NAT 设备后面的客户端更加友好。由于这种模式下是客户端自动发起连接,符合大多数防火墙的安全计谋,即答应内部网络的主机自动向外发起连接。
    被动缺点:
    服务器须要额外的配置来支持被动模式。而且在一些环境下,服务器可能会受到恶意攻击,例如攻击者可能会实验扫描服务器返回的临时端口号,以寻找安全弊端。
最终的方案

在每次客户端连接的时候,就要告诉服务器,我们是被动方式连接,添加这行代码设置:
  1. //设置为被动模式
  2. ftpClient.enterLocalPassiveMode();
复制代码
注意:ftp server可能每次开启差别的端口来传输数据,但是在linux 上,由于安全限制,可能某些端口没有开启,所以就出现阻塞。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

水军大提督

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表