在Java开发中,通过FTP协议获取服务器上的文件名称是常见的文件操作需求,例如动态获取最新文件、批量处理文件列表或筛选特定类型的文件,本文将详细介绍几种主流的实现方法,涵盖基础FTP操作及异常处理,帮助开发者高效完成文件名称获取任务。

使用Apache Commons Net库实现FTP文件名称获取
Apache Commons Net是Java中广泛使用的网络工具库,提供了完整的FTP客户端实现,支持文件列表获取、上传下载等功能,其核心类FTPClient封装了FTP协议的操作,通过listNames()或listFiles()方法可轻松获取文件名称。
实现步骤
-
添加依赖:在项目中引入Apache Commons Net库(Maven依赖如下):
<dependency> <groupId>commons-net</groupId> <artifactId>commons-net</artifactId> <version>3.9.0</version> </dependency> -
核心代码实现:

import org.apache.commons.net.ftp.FTP; import org.apache.commons.net.ftp.FTPClient; import org.apache.commons.net.ftp.FTPFile; import java.io.IOException; import java.util.Arrays; public class FtpFileNameGetter { public static void main(String[] args) { String server = "ftp.example.com"; int port = 21; String username = "user"; String password = "password"; String remoteDir = "/remote/path/"; FTPClient ftpClient = new FTPClient(); try { // 连接FTP服务器 ftpClient.connect(server, port); if (!ftpClient.login(username, password)) { System.out.println("FTP登录失败"); return; } // 设置文件传输模式为被动模式(避免防火墙问题) ftpClient.enterLocalPassiveMode(); // 设置编码(解决中文文件名乱码问题) ftpClient.setControlEncoding("UTF-8"); // 切换到目标目录 if (!ftpClient.changeWorkingDirectory(remoteDir)) { System.out.println("切换目录失败: " + remoteDir); return; } // 方法1:获取文件名称列表(字符串数组) String[] fileNames = ftpClient.listNames(); System.out.println("文件名称列表:" + Arrays.toString(fileNames)); // 方法2:获取FTPFile对象列表(包含文件大小、修改时间等元数据) FTPFile[] ftpFiles = ftpClient.listFiles(); System.out.println("文件详细信息:"); for (FTPFile file : ftpFiles) { if (file.isFile()) { // 过滤掉目录 System.out.println("文件名:" + file.getName() + ",大小:" + file.getSize() + "B,修改时间:" + file.getTimestamp().getTime()); } } } catch (IOException e) { System.err.println("FTP操作异常:" + e.getMessage()); } finally { try { if (ftpClient.isConnected()) { ftpClient.logout(); ftpClient.disconnect(); } } catch (IOException e) { e.printStackTrace(); } } } }
关键点说明
- 编码问题:FTP服务器可能使用不同的字符编码(如GBK、ISO-8859-1),需通过
setControlEncoding()设置与服务器一致的编码,否则文件名可能乱码。 - 被动模式:
enterLocalPassiveMode()可解决NAT环境下连接被防火墙阻断的问题。 - 文件过滤:
listFiles()返回的FTPFile数组包含目录和文件,需通过file.isFile()筛选出文件。
使用JSch库实现SFTP文件名称获取
相较于传统FTP,SFTP(基于SSH的文件传输协议)更安全,常用于企业级应用,JSch是Java中实现SFTP的常用库,通过ChannelSftp通道操作远程文件。
实现步骤
-
添加依赖:
<dependency> <groupId>com.jcraft</groupId> <artifactId>jsch</artifactId> <version>0.1.55</version> </dependency> -
核心代码实现:

import com.jcraft.jsch.*; import java.util.Vector; public class SftpFileNameGetter { public static void main(String[] args) { String host = "sftp.example.com"; int port = 22; String username = "user"; String password = "password"; String remoteDir = "/remote/path/"; JSch jsch = new JSch(); Session session = null; ChannelSftp channelSftp = null; try { // 创建Session并连接 session = jsch.getSession(username, host, port); session.setPassword(password); session.setConfig("StrictHostKeyChecking", "no"); session.connect(); // 打开SFTP通道 Channel channel = session.openChannel("sftp"); channel.connect(); channelSftp = (ChannelSftp) channel; // 切换到目标目录 channelSftp.cd(remoteDir); // 获取文件列表 Vector<ChannelSftp.LsEntry> fileVector = channelSftp.ls("."); System.out.println("SFTP文件列表:"); for (ChannelSftp.LsEntry entry : fileVector) { String fileName = entry.getFilename(); // 过滤掉"."和".."目录 if (!fileName.equals(".") && !fileName.equals("..")) { System.out.println("文件名:" + fileName + ",类型:" + (entry.getAttrs().isDir() ? "目录" : "文件")); } } } catch (JSchException | SftpException e) { System.err.println("SFTP操作异常:" + e.getMessage()); } finally { if (channelSftp != null) { channelSftp.disconnect(); } if (session != null) { session.disconnect(); } } } }
关键点说明
- Session配置:
setConfig("StrictHostKeyChecking", "no")用于跳过主机密钥验证(生产环境建议配置密钥认证)。 - 文件列表解析:
ls()方法返回Vector<LsEntry>,通过getFilename()获取文件名,getAttrs()判断文件类型。
注意事项与最佳实践
- 异常处理:FTP/SFTP操作可能因网络、权限、路径等问题抛出异常,需捕获
IOException、JSchException等并处理,避免程序中断。 - 资源释放:确保在
finally块中关闭FTPClient、Session等资源,防止连接泄漏。 - 性能优化:若文件数量较多,可结合
listNames()获取文件名后,再通过多线程或分页处理文件内容,避免内存溢出。 - 安全加固:避免在代码中硬编码FTP/SFTP凭据,建议使用配置文件或环境变量存储敏感信息。
Java中获取FTP/SFTP文件名称可通过Apache Commons Net或JSch库实现,前者适合传统FTP协议,后者支持更安全的SFTP协议,开发时需注意编码、异常处理、资源释放等细节,并根据业务场景选择合适的方法,通过合理封装工具类,可进一步提升代码复用性和可维护性。