用commons-net包写Ftp客户端下载(二)

上次写完了工具类,那么然后就是另一个工具类了。

1.也就是对ftp上文件的遍历。

这里我发现了一个问题,下载文件的时候,每次都得重新连接,也就是一次连接只能下载一个文件。

虽然到最后我也没发现到底为啥是这样,但是我自己的测试是的确这样的。

所有下载的思路我就设置成,第一次连接,遍历出所有FTP服务器上的文件,然后根据遍历之后的结果进行下载。

这里我又遇到问题了,我经过遍历需要得到什么结果,才能下载,首先文件名字吧。然后文件在ftp的相对路径。也就是工作空间

关于路径,由于在commons-net里面封装了ftp上文件类就是org.apache.commons.net.ftp.FTPFile

但是你会发现,这个类中没有方法得到路径,这就郁闷了,竟然没有任何方法能后看出来这个文件是什么路径。那怎么知道某个文件的工作空间在什么地方。于是只能遍历了。。。

(但是到最后大家会发现,我这里用的递归遍历,消耗的时间太长,如果ftp文件少没问题,然后数量大了,光遍历的时间就太长了。。。。。。。所以之后遍历被抛弃了,解决版本下此说)

首先我先建立了一个封装我自己的类,就是封装了FTP文件的信息包括名字和其所有的工作空间。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
importjava.io.Serializable;
importjava.util.ArrayList;
importjava.util.List;
 
 
 
/**
 *
 * ftp上文件的封装
 * @author houly
 *
 */
 
 
publicclassFtpFileimplementsSerializable {
    /**
     *
     */
    privatestaticfinallongserialVersionUID = -438376767446894227L;
    /**文件对应的工作空间,自上而下依次*/
    privateList<String> list =newArrayList<String>();
    /**文件名称*/
    privateString fileName ;
 
     
     
     
    publicFtpFile() {
        super();
    }
 
    publicFtpFile(List<String> list, String fileName) {
        super();
        this.list = list;
        this.fileName = fileName;
    }
 
    publicList<String> getList() {
        returnlist;
    }
 
    publicvoidsetList(List<String> list) {
        this.list = list;
    }
 
    publicString getFileName() {
        returnfileName;
    }
 
    publicvoidsetFileName(String fileName) {
        this.fileName = fileName;
    }
 
     
     
    @Override
    publicinthashCode() {
        finalintprime =31;
        intresult =1;
        result = prime * result
                + ((fileName ==null) ?0: fileName.hashCode());
        result = prime * result + ((list ==null) ?0: list.hashCode());
        returnresult;
    }
 
    @Override
    publicbooleanequals(Object obj) {
        if(this== obj)
            returntrue;
        if(obj ==null)
            returnfalse;
        if(getClass() != obj.getClass())
            returnfalse;
        FtpFile other = (FtpFile) obj;
        if(fileName ==null) {
            if(other.fileName !=null)
                returnfalse;
        }elseif(!fileName.equals(other.fileName))
            returnfalse;
        if(list ==null) {
            if(other.list !=null)
                returnfalse;
        }elseif(!list.equals(other.list))
            returnfalse;
        returntrue;
    }
 
    @Override
    publicString toString() {
        return"FtpFile [fileName="+ fileName +", list="+ list +"]";
    }
     
     
}

然后就是遍历方法了。。。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
importjava.util.ArrayList;
importjava.util.List;
 
importorg.apache.commons.net.ftp.FTPFile;
importorg.apache.log4j.Logger;
 
 
importdomain.FtpFile;
/**
 * 遍历ftp上所有文件的工具类
 * @author houly
 *
 */
publicclassFtpTraversal {
    //日志
    privateLogger logger = Logger.getLogger(FtpShow.class);
    //存放遍历出来文件的集合
    privateList<FtpFile> list =newArrayList<FtpFile>();
    //ftp工具类
    privateFtpHelper ftpHelper;
 
    publicFtpTraversal(FtpHelper ftpHelper) {
        this.ftpHelper = ftpHelper;
    }
     
    /**
     * 遍历出来FTP里面所有文件
     * @param remotePath 当前工作目录
     * @param list 路径集合
     */
    publicvoidlistAllFiles(String remotePath, List<String> list) {
        logger.info("开始遍历"+remotePath+"目录......");
         
        //判断是否是开始目录
        if("/".equals(remotePath) && list ==null) {
            FTPFile[] files = ftpHelper.getFilesList();
            List<String> strings =newArrayList<String>();
            strings.add(remotePath);
            for(inti =0; i < files.length; i++) {
                if(files[i].isFile()) {
                    //如果是文件,就保存路径,放在文件结合当总
                    getList().add(newFtpFile(strings, files[i].getName()));
                }else{
                    List<String> s1 =newArrayList<String>(strings);
                    //把当前工作目录保存下载
                    s1.add(files[i].getName());
                    listAllFiles(files[i].getName(), s1);
                    //返回到父目录
                    ftpHelper.changeToParentDir();
                }
            }
 
        }else{
            //把工作目录跳转到remotePath下
            ftpHelper.changeDir(remotePath);
            //列出里面的所有文件
            FTPFile[] files = ftpHelper.getFilesList();
 
            //如果文件夹下没有文件
            if(files ==null) {
                // ftpHelper.changeToParentDir();
                // list.remove(list.size()-1);
                // ftpHelper.changeToParentDir();
                return;
            }
 
            intflag =0;
            for(inti =0; i < files.length; i++) {
                //System.out.println(files[i].getName());
                if(files[i].isFile()) {
                    //如果是文件
                    getList().add(newFtpFile(list, files[i].getName()));
                    flag++;
                }else{
                    //不是文件
                    List<String> s1 =newArrayList<String>(list);
                    s1.add(files[i].getName());
                    //递归调用
                    listAllFiles(files[i].getName(), s1);
                    //返回上级工作空间
                    ftpHelper.changeToParentDir();
                }
            }
             
            //如果目录下没有文件,即使空目录
            if(flag == files.length) {
                // ftpHelper.changeToParentDir();
                // list.remove(list.size()-1);
                return;
            }
 
        }
        return;
    }
 
    publicList<FtpFile> getList() {
        returnlist;
 
    }
 
    publicvoidsetList(List<FtpFile> list) {
        this.list = list;
    }
 
    publicFtpHelper getFtpHelper() {
        returnftpHelper;
    }
 
    publicvoidsetFtpHelper(FtpHelper ftpHelper) {
        this.ftpHelper = ftpHelper;
    }
 
}

这里的递归其实可以写的更好看的,但是时间比较紧急,没办法修改还了。请见谅。。

其实这里的意思就是从根目录开始,得到里面的所有文件,然后如果是目录进行递归,如果是文件那么保存生成

我自己的FtpFile类,把文件名和工作空间保存下来。

这里有人会问为啥工作空间需要一个数组或者List来保存,因为变更工作目录的时候一次只能变更一个工作空间。。

2.然后就是文件下载了。

其实很简单,根据遍历结果,拼成本地目录,然后调用工具类里面的文件下载方法,即可。。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
publicbooleanexecuteDownload() {
        logger.info("进入FtpDownloadServiceImpl的executeDownload方法");
        // 建立FTP连接工具类
        FtpHelper ftpHelper =newFtpHelper();
 
        // 根据配置文件连接FTP服务器
        booleanb = ftpHelper.connect(ConfigInfo.getFtpHostName(), ConfigInfo
                .getPort(), ConfigInfo.getUsername(), ConfigInfo.getPassword());
        if(!b) {
            logger.error("连接不上.....");
            returnfalse;
        }
//       遍历FTP服务器上所有文件
        FtpShow ftpShow =newFtpShow(ftpHelper);
 
        ftpShow.listAllFiles("/",null);
 
        List<FtpFile> list = ftpShow.getList();
        intnum = list.size();
        logger.info("遍历ftp目录里面文件的个数为"+ num);
 
 
         
        ftpHelper.disconnect();
 
        String local_downLoad_dir = ConfigInfo.getFtpDownLoadDir();
        logger.info("得到配置文件中下载目录为:"+ local_downLoad_dir);
 
        intflag =0;
        //根据遍历结果从FTP上下载文件
        intcount =0;
        for(FtpFile file : list) {
            count++;
            logger.info("开始下载"+num+"个文件中的第"+count+"个文件");
            //FTP连接
            ftpHelper =newFtpHelper();
            ftpHelper.connect(ConfigInfo.getFtpHostName(),
                    ConfigInfo.getPort(), ConfigInfo.getUsername(), ConfigInfo
                            .getPassword());
             
            //该文件工作空间集合
            List<String> filepath = file.getList();
            //文件下载到本地的路径
            String local_path = local_downLoad_dir;
             
            // 变更工作目录
            // 组合下载路径
            for(inti =0; i < filepath.size(); i++) {
                //如果是空间默认的开始工作空间
                if("/".equals(filepath.get(i))) {
                    local_path += filepath.get(i);
                }else{
                    //其他的工作空间
                     
                    //变更工作空间
                    ftpHelper.changeDir(filepath.get(i));
                     
                    //组合本地路径
                    local_path += filepath.get(i) +"/";
                }
            }
 
            logger.info("组合之后下载目录为:"+ local_path);
             
            //如果本地工作路径不存在,建立目录
            File local_file =newFile(local_path);
            if(!local_file.exists()) {
                local_file.mkdirs();
            }
             
            //进行下载并返回下载结果
            Boolean status = ftpHelper.downloadonefile(file
                    .getFileName(), local_path + file.getFileName());
 
            if(!status)
                flag++;
 
            //断开FTP连接
            ftpHelper.disconnect();
 
        }
 
 
        logger.info("进入FtpDownloadServiceImpl的executeDownload方法结束");
        if(flag !=0) {
            returnfalse;
        }
 
        returntrue;
    }

这个我觉得没啥好说的了,注释写的很清楚了。。。

这只是中间过程中的一个版本,虽然后来被抛弃了。。。但是还有有点意义的。。

就是遍历时间太长了。。。

你可能感兴趣的:(Ftp客户端下载)