用Java(Apache Net Commons)下载整个FTP目录

用Java(Apache Net Commons)下载整个FTP目录,java,ftp,apache-commons-net,Java,Ftp,Apache Commons Net,我试图递归地遍历登录到FTP服务器后到达的整个根目录 我能够连接,我真正想做的就是在整个结构中递归,下载每个文件和文件夹,并使其与FTP上的结构相同。到目前为止,我拥有的是一种有效的下载方法,它进入服务器并获取我的整个文件结构,这非常棒,只是第一次尝试失败,然后第二次就可以了。我得到的错误如下: java.io.FileNotFoundException:output directory\test\testFile.png (系统找不到指定的路径) 我设法上传了一个我在本地拥有的目录的功能,但无

我试图递归地遍历登录到FTP服务器后到达的整个根目录

我能够连接,我真正想做的就是在整个结构中递归,下载每个文件和文件夹,并使其与FTP上的结构相同。到目前为止,我拥有的是一种有效的下载方法,它进入服务器并获取我的整个文件结构,这非常棒,只是第一次尝试失败,然后第二次就可以了。我得到的错误如下:

java.io.FileNotFoundException:output directory\test\testFile.png (系统找不到指定的路径)

我设法上传了一个我在本地拥有的目录的功能,但无法完全下载,在多次尝试之后,我真的需要一些帮助

public static void download(String filename, String base)
{
    File basedir = new File(base);
    basedir.mkdirs();

    try
    {
        FTPFile[] ftpFiles = ftpClient.listFiles();
        for (FTPFile file : ftpFiles)
        {
            if (!file.getName().equals(".") && !file.getName().equals("..")) {
                // If Dealing with a directory, change to it and call the function again
                if (file.isDirectory())
                {
                    // Change working Directory to this directory.
                    ftpClient.changeWorkingDirectory(file.getName());
                    // Recursive call to this method.
                    download(ftpClient.printWorkingDirectory(), base);

                    // Create the directory locally - in the right place
                    File newDir = new File (base + "/" + ftpClient.printWorkingDirectory());
                    newDir.mkdirs();

                    // Come back out to the parent level.
                    ftpClient.changeToParentDirectory();
                }
                else
                {
                    ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
                    String remoteFile1 = ftpClient.printWorkingDirectory() + "/" + file.getName();
                    File downloadFile1 = new File(base + "/" + ftpClient.printWorkingDirectory() + "/" + file.getName());
                    OutputStream outputStream1 = new BufferedOutputStream(new FileOutputStream(downloadFile1));
                    boolean success = ftpClient.retrieveFile(remoteFile1, outputStream1);
                    outputStream1.close();
                }
            }
        }
    }
    catch(IOException ex)
    {
        System.out.println(ex);
    }
}
您的问题(好的,您当前的问题是,在我们摆脱了
之后,您已经克服了二进制问题)是,在调用
newDir.mkdirs()之前,您正在执行递归步骤

所以假设你有一棵像树一样的树

。
..
萨默迪尔
.
..
someFile.txt
其他人
.
..
someOtherFile.png
您要做的是跳过点文件,查看
someDir
是一个目录,然后立即进入其中,跳过它的点文件,查看
someFile.txt
,并对其进行处理。您尚未在本地创建
someDir
,因此会出现异常

异常处理程序不会停止执行,所以控制返回到递归的上层。此时,它将创建目录

因此,下次运行程序时,本地
someDir
目录已经从上一次运行中创建,您不会发现任何问题

基本上,您应该将代码更改为:

            if (file.isDirectory())
            {
                // Change working Directory to this directory.
                ftpClient.changeWorkingDirectory(file.getName());

                // Create the directory locally - in the right place
                File newDir = new File (base + "/" + ftpClient.printWorkingDirectory());
                newDir.mkdirs();

                // Recursive call to this method.
                download(ftpClient.printWorkingDirectory(), base);

                // Come back out to the parent level.
                ftpClient.changeToParentDirectory();
            }

从FTP文件夹递归下载所有文件的完整独立代码:

private static void downloadFolder(
    FTPClient ftpClient, String remotePath, String localPath) throws IOException
{
    System.out.println("Downloading folder " + remotePath + " to " + localPath);

    FTPFile[] remoteFiles = ftpClient.listFiles(remotePath);

    for (FTPFile remoteFile : remoteFiles)
    {
        if (!remoteFile.getName().equals(".") && !remoteFile.getName().equals(".."))
        {
            String remoteFilePath = remotePath + "/" + remoteFile.getName();
            String localFilePath = localPath + "/" + remoteFile.getName();

            if (remoteFile.isDirectory())
            {
                new File(localFilePath).mkdirs();

                downloadFolder(ftpClient, remoteFilePath, localFilePath);
            }
            else
            {
                System.out.println("Downloading file " + remoteFilePath + " to " +
                    localFilePath);

                OutputStream outputStream =
                    new BufferedOutputStream(new FileOutputStream(localFilePath));
                if (!ftpClient.retrieveFile(remoteFilePath, outputStream))
                {
                    System.out.println("Failed to download file " + remoteFilePath);
                }
                outputStream.close();
            }
        }
    }
}

您尝试了什么,失败在哪里?添加了代码,向您显示当前代码的确切位置。谢谢你的快速回复。那么,你尝试了什么(不是正在工作的部分,你说你尝试了但失败了的部分),以及失败的原因是什么?如果你提到过程中的哪一部分会给你带来麻烦,帮助会更容易——当你开始下载文件时?穿越远程方向?递归遍历?保留文件夹结构?好吧,当我在for循环中有下载代码,以及用于目录案例的mkdirs()时,我发现我没有得到任何接近ftp服务器中的结构的东西。而且,我现在所拥有的东西不起作用了——它甚至无法正确打印文件或目录名,我完全不知道为什么。非常感谢您的帮助!这是我在堆栈溢出问题上得到的最好的帮助,你让我自己解决问题,并在进行过程中进行必要的更改。我学到了一些新东西,而不仅仅是一堆代码:)