我在百度、google上找了很多,但都不好用,请各位高手给一个好用的
sun.net.ftp.FtpClient可以
apache的commons.ftp可以
总之用什么包都可以,只要实现能把ftp服务器上的文件夹下载下来就行,文件夹里包括多少文件和文件夹,以及文件夹里的文件夹和子文件,都下载,递归算法,自动覆盖本地路径中的同名文件和文件夹

解决方案 »

  1.   

    很好很强大,先list再下载,如果是目录继续list
      

  2.   

    http://blog.sina.com.cn/s/blog_4ca11ce00100bgw0.htmlpublic  void listRemoteAllFiles(String path) {
          try {
        FTPListParseEngine f = ftpClient.initiateListParsing(path);
        
           while (f.hasNext()) {
               FTPFile[] files = f.getNext(5); 
               for(FTPFile file:files){
                disFile(file,path);
               }
            }   } catch (IOException e) {
        e.printStackTrace();
       }
        }
      

  3.   


    //使用Sun的FtpClient做FTP上传下载 
    import sun.net.*;
    import sun.net.ftp.*;
    import java.io.*;
    import java.util.*;
    /**
    FTP远程命令列表<br>
    USER    PORT    RETR    ALLO    DELE    SITE    XMKD    CDUP    FEAT<br>
    PASS    PASV    STOR    REST    CWD     STAT    RMD     XCUP    OPTS<br>
    ACCT    TYPE    APPE    RNFR    XCWD    HELP    XRMD    STOU    AUTH<br>
    REIN    STRU    SMNT    RNTO    LIST    NOOP    PWD     SIZE    PBSZ<br>
    QUIT    MODE    SYST    ABOR    NLST    MKD     XPWD    MDTM    PROT<br>
    在服务器上执行命令,如果用sendServer来执行远程命令(不能执行本地FTP命令)的话,所有FTP命令都要加上\r\n<br>
    ftpclient.sendServer("XMKD /test/bb\r\n"); //执行服务器上的FTP命令<br>
    ftpclient.readServerResponse一定要在sendServer后调用<br>
    nameList("/test")获取指目录下的文件列表<br>
    XMKD建立目录,当目录存在的情况下再次创建目录时报错<br>
    XRMD删除目录<br>
    DELE删除文件<br>
    * 针对FTP中的所有调用使用到文件名的地方请使用完整的路径名(绝对路径开始)。
    */public class FtpUtils {
        private FtpClient ftpclient;
        private String ipAddress;
        private int port;
        private String username;
        private String password;
        /**
         * 构造函数
         * @param ip String 机器IP
         * @param port String 机器FTP端口号
         * @param username String FTP用户名
         * @param password String FTP密码
         * @throws Exception
         */
        public FtpUtils(String ip, int port, String username, String password) throws
                Exception {
            this.ipAddress = ip;
            this.port = port;
            this.ftpclient = new FtpClient(ipAddress, port);
            this.username = username;
            this.password = password;
        }
        /**
         * 构造函数
         * @param ip String 机器IP,默认端口为21
         * @param username String FTP用户名
         * @param password String FTP密码
         * @throws Exception
         */
        public FtpUtils(String ip, String username, String password) throws
                Exception {
             this(ip,21,username,password);
        }
        /**
         * 登录FTP服务器
         * @throws Exception
         */
        public void login() throws Exception {
            ftpclient.login(username, password);
        }    /**
         * 退出FTP服务器
         * @throws Exception
         */
        public void logout() throws Exception {
            //用ftpclient.closeServer()断开FTP出错时用下更语句退出
            ftpclient.sendServer("QUIT\r\n");
            int reply = ftpclient.readServerResponse(); //取得服务器的返回信息
        }
        /**
         * 取得指定目录下的所有文件名,不包括目录名称
         * 分析nameList得到的输入流中的数,得到指定目录下的所有文件名
         * @param fullPath String
         * @return ArrayList
         * @throws Exception
         */
        public ArrayList fileNames(String fullPath) throws Exception {
            ftpclient.ascii(); //注意,使用字符模式
            TelnetInputStream list = ftpclient.nameList(fullPath);
            byte[] names = new byte[2048];//如果文件数目很多,有可能溢出
            int bufsize = 0;
            bufsize = list.read(names, 0, names.length); //从流中读取
            list.close();
            ArrayList namesList = new ArrayList();
            int i = 0;
            int j = 0;
            while (i < bufsize ) {
                if (names[i] == 10) { //字符模式为10,二进制模式为13
                    String tempName = new String(names, j, i - j);
                    namesList.add(tempName);
                    //j = i + 2; //上一次位置二进制模式
                    j = i + 1; //上一次位置字符模式
                }
                i = i + 1;
            }
            return namesList;
        }
        /**
         * 在FTP服务器上建立指定的目录,当目录已经存在的情下不会影响目录下的文件,这样用以判断FTP
         * 上传文件时保证目录的存在目录格式必须以"/"根目录开头
         * @param pathList String
         * @throws Exception
         */
        public void buildRemoteDir(String pathList) throws Exception {
            ftpclient.ascii();
            StringTokenizer s = new StringTokenizer(pathList, "/"); //sign
            int count = s.countTokens();
            String pathName = "";
            while (s.hasMoreElements()) {
                pathName = pathName + "/" + (String) s.nextElement();
                try {
                    ftpclient.sendServer("XMKD " + pathName + "\r\n");
                } catch (Exception e) {
                    e = null;
                }
                int reply = ftpclient.readServerResponse();
            }
            ftpclient.binary();
        }
        /**
         * 上传文件到FTP服务器,remote路径以FTP服务器的"/"开始,带文件名、
         * 上传文件只能使用二进制模式,当文件存在时再次上传则会覆盖
         * @param local String
         * @param remote String
         * @throws Exception
         */
        public void upFile(String local, String remote) throws Exception {
            buildRemoteDir(remote.substring(0, remote.lastIndexOf("/")));
            ftpclient.binary(); //此行代码必须放在buildRemoteDir之后
            TelnetOutputStream ftpOut = ftpclient.put(remote);
      InputStream in  = new FileInputStream(local);//
            byte[] buf = new byte[204800];
            int bufsize = 0;
            while((bufsize = in.read(buf, 0, buf.length)) != -1){
                  ftpOut.write(buf, 0, bufsize);
            }
            in.close();
            ftpOut.close();
        }
     public void buildLocalDir(String fullPath) throws Exception {        if(fullPath.lastIndexOf("/")<=0)return;
             String path=fullPath.substring(0,fullPath.lastIndexOf("/"));          File f= new File(path);
             if(!f.exists()){
                   f.mkdirs();
             }
      }
     public void downFile(String remote,String local) throws Exception {
         buildLocalDir(local);
         ftpclient.binary(); //此行代码必须放在buildRemoteDir之后
         OutputStream out=new FileOutputStream(new File(local));
         TelnetInputStream ftpIn = ftpclient.get(remote);
         byte[] buff=new byte[204800];
         int len=0;
         while((len=ftpIn.read(buff))!=-1){
               out.write(buff,0,len);
         }
         out.close();
         ftpIn.close();
     }
        public static void main(String args[])throws Exception{
            FtpUtils upfile=new FtpUtils("192.168.187.130","root","1-1=0");
            upfile.login();
            List list=upfile.fileNames("/");
            System.out.println(list);
            upfile.upFile("FtpUtils.java","/root/xjs/test/FtpUtils.java" );
            upfile.downFile("/root/xjs/2.txt","xjs/2.txt" );
            upfile.logout();
        }
    }
    /*
    以sun开头的class不是java里面的标准类,而是sun公司自己的的class,因此,他们位于rt.jar当中。因此,jdk源代码中没有提供源文件。但是,可以用诸如jad之类的反编译工具进行反编译。
    实际上,基本原理就是利用Socket和ServerSocket来发送遵守FTP协议的消息,与FTP服务器进行交互。
    主要用到这么几个类:
    sun.net.ftp.FtpClient extends sun.net.TransferProtocolClient
    sun.net.TransferProtocolClient extends sun.net.NetworkClient
    sun.net.TelnetInputStream extends FilterInputStream
    sun.net.TelnetOutputStream extends BufferedOutputStream
    因为是使用被动模式,因此,客户端要去连接服务端,
    在FtpClient的源代码的openDataConnection(String s)方法中有这么一句:
    serversocket = new ServerSocket(0, 1);也就是客户端随便选择一个空闲端口。
    也就是说,sun的FtpClient不支持主动模式。
    */