【问题标题】:ant ftp doesn't download files in subdirectoriesant ftp 不下载子目录中的文件
【发布时间】:2011-02-16 22:45:15
【问题描述】:

我正在尝试使用 ant 从 ftp 服务器下载子目录中的文件。 确切的文件集是已知的。 其中一些位于子目录中。 Ant似乎只下载根目录中的那些。 如果我下载所有文件而不列出它们,它确实有效。

第一个 ftp 操作应该与第二个操作完全相同。 相反,我得到“隐藏文件 \\a\a.txt 假定不是符号链接。”

有人知道这里出了什么问题吗? 这是ant FTP任务的bug吗?

<?xml version="1.0" encoding="utf-8"?>
<project name="example" default="example" basedir=".">
    <taskdef name="ftp" 
    classname="org.apache.tools.ant.taskdefs.optional.net.FTP" />

    <target name="example">

        <!-- doesn't work -->
        <ftp action="get" verbose="true"
        server="localhost" userid="example" password="example" 
        remotedir="">
            <fileset dir="downloads" casesensitive="false" 
            includes="a/a.txt,a/b/ab.txt,c/c.txt" />
        </ftp>

        <!-- works (but requires multiple ftp tasks) -->
        <ftp action="get" verbose="true"
        server="localhost" userid="example" password="example"
        remotedir="a">
            <fileset dir="downloads" casesensitive="false" 
            includes="a.txt,b/ab.txt" />
        </ftp>
        <ftp action="get" verbose="true"
        server="localhost" userid="example" password="example"
        remotedir="c">
            <fileset dir="downloads" casesensitive="false" 
            includes="c.txt" />
        </ftp>

    </target>

</project>

更新:我向 Commons Net jira 发布了一个关于此的错误 https://issues.apache.org/jira/browse/NET-324

更新:我在ant bugreport系统中添加了一个bugreport https://issues.apache.org/bugzilla/show_bug.cgi?id=49296

【问题讨论】:

    标签: ant ftp apache-commons-net


    【解决方案1】:

    因为我需要它来工作,所以我做了这个解决方法。 它似乎有效,但我对此并不完全满意。 感觉不干净。

    <scriptdef name="my-ftp-get" language="javascript">
        <attribute name="server"/>
        <attribute name="userid"/>
        <attribute name="password"/>
        <attribute name="remotedir"/>
        <attribute name="fileset_dir"/>
        <attribute name="fileset_includes"/>
        <![CDATA[
        importClass(java.io.File);
        importClass(org.apache.tools.ant.taskdefs.optional.net.FTP);
        var local_basedir = "" + attributes.get("fileset_dir") + "/";
        var original_includes = "" + attributes.get("fileset_includes");
        var remotedir = "" + attributes.get("remotedir");
        local_basedir = local_basedir.replace(/\\/g, "/");
        original_includes = original_includes.replace(/\\/g, "/");
        remotedir = remotedir.replace(/\\/g, "/");
        var includes_arr = original_includes.split(",");
        var clean_includes = {};
        for (var i = 0; i < includes_arr.length; i++) {
            var directory = "/";
            var filename = includes_arr[i];
            var split_include = includes_arr[i].split("/");
            if (split_include.length > 1) {
                directory = split_include[0] + "/";
                filename = includes_arr[i].substring(directory.length);
            }
            if (!clean_includes.hasOwnProperty(directory)) {
                clean_includes[directory] = [];
            }
            clean_includes[directory].push(filename);
        }
        var get_files = new FTP.Action();
        get_files.setValue("get");
        for (var path in clean_includes) {
            var current_clean_includes = clean_includes[path].join(",");
            var fileset = project.createDataType("fileset");
            var ftp = self.project.createTask("ftp");
            ftp.setAction(get_files);
            ftp.setServer(attributes.get("server"));
            ftp.setUserid(attributes.get("userid"));
            ftp.setPassword(attributes.get("password"));
            ftp.setRemotedir(remotedir + path);
            fileset.setDir(new File(local_basedir + path));
            fileset.setIncludes(current_clean_includes);
            ftp.addFileset(fileset);
            ftp.perform();
        }
        ]]>
    </scriptdef>
    
    <my-ftp-get
    server="localhost" userid="example" password="example"
    remotedir=""
        fileset_dir="downloads" casesensitive="false" 
        fileset_includes="a/a.txt,a/b/ab.txt">
    </my-ftp-get>
    

    【讨论】:

      【解决方案2】:

      我相信已经发现并解决了问题。 另请参阅我在 jira 中的错误报告:https://issues.apache.org/jira/browse/NET-324

      我已经在 ant bugreport 系统https://issues.apache.org/bugzilla/show_bug.cgi?id=49296添加了一个 bugreport

      diff --git a/libs/apache-ant-1.8.1/src/main/org/apache/tools/ant/taskdefs/optional/net/FTP.java b/libs/apache-ant-1.8.1/src/main/org/apache/tools/ant/taskdefs/optional/net/FTP.java
      --- a/libs/apache-ant-1.8.1/src/main/org/apache/tools/ant/taskdefs/optional/net/FTP.java
      +++ b/libs/apache-ant-1.8.1/src/main/org/apache/tools/ant/taskdefs/optional/net/FTP.java
      @@ -834,8 +834,7 @@
                               } else if (!result) {
                                   return;
                               }
      -                        this.curpwd = this.curpwd + remoteFileSep
      -                            + currentPathElement;
      +                        this.curpwd = getCurpwdPlusFileSep() + currentPathElement;
                           } catch (IOException ioe) {
                               throw new BuildException("could not change working dir to "
                                                        + (String) pathElements.elementAt(fcount)
      @@ -895,7 +894,7 @@
                    * @return absolute path as string
                    */
                   public String getAbsolutePath() {
      -                return curpwd + remoteFileSep + ftpFile.getName();
      +                return getCurpwdPlusFileSep() + ftpFile.getName();
                   }
                   /**
                    * find out the relative path assuming that the path used to construct
      @@ -1036,6 +1035,17 @@
                   public String getCurpwd() {
                       return curpwd;
                   }
      +
      +            /**
      +             * @return parent directory of the AntFTPFile with a remoteFileSep appended
      +             */
      +            private String getCurpwdPlusFileSep() {
      +                if (this.curpwd.endsWith(remoteFileSep)) {
      +                    return this.curpwd;
      +                }
      +                return this.curpwd + remoteFileSep;
      +            }
      +            
                   /**
                    * find out if a symbolic link is encountered in the relative path of this file
                    * from rootPath.
      

      【讨论】:

        【解决方案3】:

        您是否已经尝试将“/”设置为 remotedir 的值?

        <ftp action="get" verbose="true"
           server="localhost" userid="example" password="example" 
           remotedir="/">
          <fileset dir="downloads" casesensitive="false" 
            includes="a/a.txt" />
        </ftp>
        

        【讨论】:

          【解决方案4】:

          我不知道设置remotedir="" 是否合法。如果你想使用默认的根目录,那么你应该完全忽略它。

          【讨论】:

            【解决方案5】:

            第一种情况会尝试获取文件 //downloads/a/a.txt 第二种情况会尝试获取文件//a/downloads/a.txt

            如果你替换了那个不起作用的

            <ftp action="get" verbose="true"
                server="localhost" userid="example" password="example" 
                remotedir="">
                    <fileset dir="a/downloads" casesensitive="false" 
                    includes="a.txt" />
            </ftp>
            

            或

            <ftp action="get" verbose="true"
                server="localhost" userid="example" password="example" 
                remotedir="">
                    <fileset dir="a" casesensitive="false" 
                    includes="downloads/a.txt" />
            </ftp>
            

            它应该工作得更好。如果这些不符合您的需求,您能否提供您想要匹配的文件的完整路径,也许我们可以创建一些替代方案。

            【讨论】:

            • 不,您混淆了 remoteDir 和文件集 dir 属性。引用手册:“从 FTP 服务器获取文件的工作方式与发送它们的方式几乎相同。唯一的区别是嵌套文件集使用 remotedir 属性作为 FTP 服务器上文件的基本目录,而 dir属性作为将文件放入的本地目录。"
            • 我想下载根目录下的几个文件和不同子目录下的几个文件。举个例子:root.txt、a/a.txt、a/b/ab.txt、c/c.txt
            【解决方案6】:

            Apache Commons VFS Ant Tasks 可能会让您获得更大的成功。这些提供对各种文件系统的读/写,并进行复制。同步等操作。如果您以后需要更改为使用 sftp、ssh、http 或其他一些系统,这也是一个灵活的解决方案;与 ftp、ssh 等的本机 ant 任务不同,大部分 VFS 配置独立于文件系统,文件系统细节大多只需要更改 URL。

            您的示例将按照以下方式进行编码:

            <taskdef resource="org/apache/commons/vfs/tasks/tasks.properties"/>
            
            <target name="example">
                 <v-copy destdir="${basedir}" srcdir="ftp://example:example@localhost/downloads" includes="a/a.txt,a/b/ab.txt,c/c.txt"/>
            </target>
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2011-07-10
              • 2016-08-30
              • 2018-07-18
              • 2012-02-13
              • 1970-01-01
              • 2017-08-06
              相关资源
              最近更新 更多