java连接ftp部署在k8s中无法读取文件

起因

最近工作中需要使用到ftp工具,就在网上找了一个java编写的ftp工具类,功能也是挺齐全的,我在本地测试的时候对文件的下载和上传都是没有问题,正常使用。等到功能开发完成后,部署到k8s就出现了无法读取ftp服务器的文件的情况,起初以为是ftp服务器的问题,就又重新搭建了新的ftp服务器还是同样的问题。中间也想过是不是工具类的功能,就在网上查询了好久,大家基本都是用的commons-net这个包,具体的maven依赖如下:

<dependency>
  <groupId>commons-net</groupId>
  <artifactId>commons-net</artifactId>
  <version>3.6</version>
</dependency>

以为网上找的工具有问题,后来就引用了hutool工具类中的方法,还是同样的问题,百思不得其解的时候,看到hutool工具类那里有一个标题:主动模式和被动模式。起初我也没注意这个,毕竟是一堆的理论。实在是被这个问题虐的体无完肤的时候,我看了一下这个概念,恍然大悟,不就是因为这个原因吗?下面我们来解释一下这两个模式

 

PORT和PASV

在解释具体的概念前,我们先来说明一下主动和被动它针对的对象是谁,其实主动和被动都是针对ftp服务器来说的。下面我们来说明一下两个模式

PORT(主动模式)

FTP客户端连接到FTP服务器的21端口,发送用户名和密码登录,登录成功后要list列表或者读取数据时

客户端随机开放一个端口(1024以上),发送 PORT命令到FTP服务器,告诉服务器客户端采用主动模式并开放端口;

FTP服务器收到PORT主动模式命令和端口号后,通过服务器的20端口和客户端开放的端口连接,发送数据。

此模式是ftp服务器主动连接客户端的一个端口,并提供文件上传和下载服务,所以客户端需要开发端口的权限出来,防火墙进行放行,这样子ftp服务器才能连接到客户端进行文件处理。

PASV(被动模式)

FTP客户端连接到FTP服务器的21端口,发送用户名和密码登录,登录成功后要list列表或者读取数据时,

客户端发送PASV命令到FTP服务器, 服务器在本地随机开放一个端口(1024以上),然后把开放的端口告诉客户端,

客户端再连接到服务器开放的端口进行数据传输。

此模式是客户端主动去连ftp服务端的端口,然后再进行文件的上传和下载,和我们正常思维逻辑是一样的,此时就需要ftp服务端开放具体的端口出来,并在防火墙中进行放行,客户端才能连接上去进行文件处理。

问题原因

这里来说明一下我遇到的问题的原因,因为我是网上找的客户端,我起初也并不清楚它使用的是主动模式还是被动模式,就直接发布到k8s中进行使用,从遇到的情况来看,应该默认使用的是主动模式:由ftp服务器主动连接客户端的高位端口,来实现文件的上传和下载。但是因为我的服务是放在k8s中,容器的端口都是需要写命令暴露出来的,而我们系统的容器都是默认只暴露了8080端口来进行服务的访问。

所以在使用主动模式的时候,ftp服务器想通过高位端口来连接到客户端是没有办法成功的,所以在获取文件的时候就什么也拿不到。

解决办法

我们知道了具体什么问题那就好解决了,解决办法也就是指定当前ftp客户端是使用主动模式还是被动模式。

因为我们的服务都是部署在k8s中的,所以我选择使用被动模式来进行文件处理,这样子k8s中的容器就不需要做什么处理。而ftp服务器则需要对高位端口进行放行,以便客户端可以连接上来进行服务的上传和下载。

代码如下:

FTPClient ftpClient = new FTPClient();

ftpClient.connect(url, port);

ftpClient.enterLocalActiveMode();    //主动模式
// ftpClient.enterLocalPassiveMode(); 被动模式
ftpClient.setControlEncoding("UTF-8");
ftpClient.changeWorkingDirectory(path);

 

THE END