Spring Integration FTP被动端口查看:getPassivePort返回-1如何解决?
问题分析与解决方案
为什么打印结果始终为-1?
被动端口是FTP客户端与服务器协商建立数据连接时才会动态分配的,你在FtpOutboundGateway初始化阶段就调用getSession().getClientInstance().getPassivePort(),此时还未触发任何实际的数据传输操作(比如mget下载),客户端还没和服务器协商被动端口,因此返回-1是正常行为。
正确查看被动端口的方法
方法1:在实际数据传输时通过SessionCallback查看
借助Spring Integration的SessionCallback,在执行具体FTP操作(如下载、列文件)的过程中获取已分配的被动端口:
@Autowired private DefaultFtpSessionFactory ftpSessionFactory; public void downloadFilesAndCheckPort(String remoteDir) { // 执行会话回调,在实际操作中查看端口 ftpSessionFactory.execute(session -> { FTPClient ftpClient = session.getClientInstance(); // 先触发数据连接(比如列出远程目录,会触发被动模式协商) FTPFile[] remoteFiles = ftpClient.listFiles(remoteDir); // 此时被动端口已分配,可正常获取 System.out.println("当前FTP被动端口:" + ftpClient.getPassivePort()); // 执行下载操作 for (FTPFile file : remoteFiles) { if (!file.isDirectory()) { try (OutputStream os = new FileOutputStream(new File(downloadPath + "/" + file.getName()))) { ftpClient.retrieveFile(file.getName(), os); } } } return null; }); }
方法2:自定义FtpSessionFactory包装类监听端口
通过包装DefaultFtpSessionFactory,在会话被使用时添加端口打印逻辑:
@Component public class MonitoredFtpSessionFactory extends DefaultFtpSessionFactory { @Override public FtpSession getSession() { FtpSession session = super.getSession(); FTPClient client = session.getClientInstance(); // 可结合AOP拦截FTP数据操作方法,在执行后打印端口 return new FtpSession() { @Override public FTPClient getClientInstance() { return client; } @Override public void close() { session.close(); } }; } }
之后在FtpOutboundGateway中使用这个自定义工厂,在实际执行mget命令时,数据连接建立后即可获取到有效端口。
方法3:利用Apache Commons Net的日志
Apache Commons Net的FTPClient本身会输出详细的FTP交互日志,开启DEBUG级别日志后,可直接在日志中查看被动端口协商过程,比如:
PASV 227 Entering Passive Mode (x,x,x,x,p1,p2).
其中p1*256 + p2就是实际使用的被动端口。
内容的提问来源于stack exchange,提问作者anna
相关产品推荐
相关产品推荐

