Java实现FTP服务器全目录递归下载(同步)问题求助
解决FTP递归同步目录到本地的问题
我明白你现在的困境啦——已经能搞定FTP根目录下的文件和文件夹创建,但子文件夹里的内容还没法同步下来对吧?其实只需要把你当前的逻辑改成递归方法就行,让程序遇到文件夹时自动钻进去处理里面的内容,处理完再回到上一级目录继续。
核心思路
当程序遍历到FTP上的文件夹时:
- 先在本地创建对应的目录
- 切换到FTP的这个子目录
- 递归调用同样的方法来处理该子目录下的所有内容
- 处理完成后切回FTP的父目录,避免后续路径混乱
修改后的完整代码
我基于你的原代码调整出了可递归的版本,完全兼容Apache Commons Net库:
import org.apache.commons.net.ftp.FTPClient; import org.apache.commons.net.ftp.FTPFile; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; public class FtpSync { public static void main(String[] args) { FTPClient ftp = new FTPClient(); try { // 填入你的FTP连接配置 ftp.connect("your-ftp-host", 21); ftp.login("your-username", "your-password"); ftp.setFileType(FTPClient.BINARY_FILE_TYPE); // 建议用二进制模式,避免非文本文件损坏 // 定义FTP根目录和本地目标目录 String remoteRootDir = "/"; String localRootDir = "D:/your-local-folder/"; // 启动递归下载 downloadDirectory(ftp, remoteRootDir, localRootDir); ftp.logout(); } catch (IOException e) { e.printStackTrace(); } finally { if (ftp.isConnected()) { try { ftp.disconnect(); } catch (IOException e) { e.printStackTrace(); } } } } /** * 递归下载FTP目录到本地 * @param ftp 已连接登录的FTPClient实例 * @param remoteDirPath FTP上的远程目录路径 * @param localDirPath 本地对应的目录路径 * @throws IOException FTP操作异常 */ private static void downloadDirectory(FTPClient ftp, String remoteDirPath, String localDirPath) throws IOException { // 递归创建本地目录(包括父目录) File localDir = new File(localDirPath); if (!localDir.exists()) { boolean created = localDir.mkdirs(); if (created) { System.out.println("创建本地目录: " + localDirPath); } } // 切换到FTP的当前远程目录 ftp.changeWorkingDirectory(remoteDirPath); // 获取当前目录下的所有文件和文件夹 FTPFile[] files = ftp.listFiles(); for (FTPFile file : files) { String fileName = file.getName(); // 跳过FTP默认的.和..目录,避免无限递归 if (fileName.equals(".") || fileName.equals("..")) { continue; } String remoteFilePath = remoteDirPath + "/" + fileName; String localFilePath = localDirPath + File.separator + fileName; if (file.isFile()) { // 下载文件,用try-with-resources自动关闭输出流 System.out.println("正在下载: " + remoteFilePath); try (OutputStream os = new BufferedOutputStream(new FileOutputStream(localFilePath))) { ftp.retrieveFile(fileName, os); } } else if (file.isDirectory()) { // 递归处理子目录 System.out.println("进入子目录: " + remoteFilePath); downloadDirectory(ftp, remoteFilePath, localFilePath); } } // 处理完当前目录后,切回FTP父目录 ftp.changeToParentDirectory(); System.out.println("返回父目录: " + ftp.printWorkingDirectory()); } }
几个关键注意点
- 用
mkdirs()代替mkdir():如果本地父目录不存在,mkdir()会创建失败,mkdirs()会自动递归创建所有必要的父目录。 - 跳过
.和..:FTP的listFiles()会返回这两个特殊目录,必须跳过,否则会陷入无限递归循环。 - 二进制模式传输:调用
ftp.setFileType(FTPClient.BINARY_FILE_TYPE),确保图片、压缩包等非文本文件不会损坏。 - 自动关闭流:用try-with-resources语法管理OutputStream,避免资源泄漏。
- 切回父目录:处理完子目录后一定要调用
changeToParentDirectory(),不然后续的文件路径会出错。
内容的提问来源于stack exchange,提问作者user9066907
相关产品推荐
相关产品推荐

