Apache commons.net FTPClient使用简述

本文遵守CC BY-SA 3.0

前言:

  之前写过个搭建FTP服务器的,搭建完成就要开始使用,网上大概看到过两种通过java来读取、写入,一种是用sun的包,还有一个就是apache的commons.net,前面那个没用过,就不展开了,这里主要介绍apache的这个,废话略多,开始正文。

   哦也,还要补充一点,由于网上信息杂乱,好多用法都是直接到官网看API文档自己摆弄的,要是有什么问题或者土鳖的用法,欢迎拍我砖&指证,下面贴出API地址:

  Apache FTPClient官方API

一、建立连接

  其实比较简单,就是首先开启连接,然后输入用户名/密码,login函数会返回个boolean,根据需要使用即可。

  值得说明的是,我总是感觉那个用户名和密码的明文组合真的很蛋疼,就自作主张的使用了一个Properties文件,把url/username/passwd都放进去了,当然,还有个basePath,这个后面的结合apache会用到,到时候再说。

  还要注意的是9,10行的两句话,

    1.setFileType(int fileType),如果没有需求上传图片的话还ok,但是要是传图片,就需要设置一下文件类型为二进制,这样上传的图片才不会报错(记得我的错误貌似是什么ASCII编码什么的。。)

    2.setControlEncoding(),设置FTP的字符编码,这个函数是从FTP父类过来的。

 1 public static FTPClient getFtpClient(Properties properties){
 2         FTPClient ftpClient = new FTPClient();
 3         try{
 4             String url = properties.getProperty("url");
 5             String username = properties.getProperty("username");
 6             String passwd = properties.getProperty("passwd");
 7             ftpClient.connect(url);
 8             ftpClient.login(username, passwd);
 9 //            ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
10 //            ftpClient.setControlEncoding("UTF-8");
11             
12         } catch (Exception e) {
13             // TODO Auto-generated catch block
14             e.printStackTrace();
15         }
16         return ftpClient;
17     }

  =============我风骚的插了进来==================

  既然说到Properties,我再贴个读取的工具函数好了,同样很简单,权当是增加篇幅。。

  需要注意以下几个事情:

  1.那个Tools其实就是个工具类,我把创建的properties文件放在了这个类的目录下面,完事直接取就行了;

  2.注意这个函数是private的,我感觉想取这个文件的话还是就在这个工具类里面就好了,也不清楚是不是多此一举(我就这么弄),有其他需求自行修改哈。。

 1 private static Properties getProperties() {
 2         InputStream inStream = Tools.class.getResourceAsStream("ftpLogin.properties");
 3         Properties properties = new Properties();
 4         try {
 5             properties.load(inStream);
 6         } catch (IOException e) {
 7             // TODO Auto-generated catch block
 8             e.printStackTrace();
 9         }
10         return properties;
11     }

  =========================================

二、文件上传

  heihei,我没使用文件下载,不过看了一下API文档,感觉也就那么回事,有需求再研究下,这里就记一下上传吧。

  下面这段代码同样有几个地方需要注意一下:

  1. 不要在意那个16行的注释,原来的第三个参数就是fileType,当时脑抽,逻辑是有问题的,放在这里警戒自己;

  2. Tools.Mkdirs():这个函数使用来创建多级目录用的,没有在API文档里面找到相关用法,也查了网上的做法,也都不高明。。干脆献丑自己搞了一段,没什么水平,需要改进,后面会贴出来;

  3. changeWorkingDirectory(path):创建完了目录需要将当前工作目录切换过来,然后直接在下面创建文件;

  4. storeFile(String remote,InputStream local): 名字是要写到的远程文件的名字,这里用了和输入文件同名,关于输入流,就是内容文件(输入文件)的输入流;

  5. sendSiteCommand(String command): 这个是在远程端执行ftp命令用的,和一个叫doCommand()的函数有点像,不过那个貌似只能操作有输出的命令,没用过,不负责任哈:-),这个函数还要多说一点,之所以这么用,是因为我发现使用storeFile()上传上去的文件都是默认700的,因为我结合了apache2服务器使用,直接导致劳资无法使用已经上传的文件,所以才有修改权限的事情;

  6. 这里其实写的还有点问题,因为我写文件的次数比较多,从这么get然后再close的用法显然在性能上面有损耗,最好在上传的时候集中一下,就是说要先get到这个ftpClient,然后再集中上传,都上传完了再close掉,不过我暂时还没有写。。

  7. 关于这一大片的tmp**,这东西我写了不少,但是一个都没用,不过倒是可以留着,等开始调试的时候会发现好处的;

  8. 关于中文编码:一共要进行两次转码,根据查询发现FTPClient默认的字符编码貌似是ISO-8859-1,而我使用的是linux平台,应该是UTF-8的,所以这里需要进行一次转码,是对文件名的,还有一次在Mkdirs()中,是对文件夹名的;

 1 /*
 2      * @param filename : the file u want to upload(without path)
 3      * 
 4      * @param path : the path u want to upload to(without filename)
 5      * 
 6      */
 7     @SuppressWarnings("resource")
 8     public static Boolean FtpUpload(File filename,String path){
 9         Boolean success = false;
10         String LOCAL_CHARSET = "GBK";
11         String SERVER_CHARSET = "ISO-8859-1";
12         try {
13             FileInputStream in = new FileInputStream(filename);
14             //get properties & get connect ftpClient
15             Properties properties = Tools.getProperties();
16             FTPClient ftpClient = Tools.getFtpClient(properties);
17             
18             // 开启服务器对UTF-8的支持,如果服务器支持就用UTF-8编码,否则就使用本地编码(GBK).
19             if(FTPReply.isPositiveCompletion(ftpClient.sendCommand("OPTS UTF8", "ON"))) {
20                 LOCAL_CHARSET = "UTF-8";
21             }
22             ftpClient.setControlEncoding(LOCAL_CHARSET);
23             
24 //            if(fileType == FTP.BINARY_FILE_TYPE){
25 //                ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
26 //            }
27             //check if connection failed
28             int reply = 0;
29             reply = ftpClient.getReplyCode();
30             if (!FTPReply.isPositiveCompletion(reply)) { 
31                 ftpClient.disconnect(); 
32                 return success;
33             }
34             //mkdirs(in case of multiple level directory)
35             if(path != null && !path.isEmpty()){
36                 //MKdirs中有关于path的转码
37                 boolean tmpMkdir = Tools.Mkdirs(ftpClient, path);
38                 System.out.println(ftpClient.printWorkingDirectory());
39                 boolean tmpCd = ftpClient.changeWorkingDirectory(path);
40                 System.out.println(ftpClient.printWorkingDirectory());
41             }
42             //上传文件时,文件名称需要做编码转换
43             String name = new String(filename.getName().getBytes(LOCAL_CHARSET),SERVER_CHARSET);
44             boolean tmpStore = ftpClient.storeFile(name, in);
45             boolean tmpDoCommand = ftpClient.sendSiteCommand("chmod 755 " + name);
46             //here is a mark that maybe i should close ftp connections after all store..
47             //like create a new function to close :-(
48             in.close();
49             ftpClient.logout();
50             success = true;
51             }catch (FileNotFoundException e1) {
52                 // TODO Auto-generated catch block
53                 e1.printStackTrace();
54             } catch (SocketException e) {
55                 // TODO Auto-generated catch block
56                 e.printStackTrace();
57             } catch (IOException e) {
58                 // TODO Auto-generated catch block
59                 e.printStackTrace();
60             } catch (Exception e){
61                 e.printStackTrace();
62             }
63         return success;
64     }

 

  ===============我又风骚的插了进来===================

  上面说到了那个创建Mkdirs的函数,在这里贴出来(话说真的写的好渣,不过比没有强哈,我会再改进,这篇博文立了好多flag,我会一个一个收的,改进是永无止境的)

  下面还是来做些说明:

  1. sendSiteCommand(): 这个函数有出现的原因是因为之前的文件上传,我只对文件进行了权限修改,这边是创建文件夹,我也做了同样的事情;

  2.创建完成之后,我又把目录弄回去了,考虑到mkdir了之后操作各有不同,就恢复了工作路径,还是那句话,根据需要自行处理;

  3. 关于中文编码:上面提到过,一共需要两次转码,之前一次是对文件名进行转码,在这里则对文件夹名进行转码;

 1 public static Boolean Mkdirs(FTPClient ftpClient,String path){
 2         Boolean success = false;
 3         String[] subDirs = path.split("/");
 4         
 5         String LOCAL_CHARSET = "GBK";
 6         String SERVER_CHARSET = "ISO-8859-1";
 7         
 8         //check if is absolute path
 9         if(path.substring(0, 0).equalsIgnoreCase("/")){
10             subDirs[0] = "/" + subDirs[0];
11         }
12         boolean tmpMkdirs = false;
13         try {
14             // 开启服务器对UTF-8的支持,如果服务器支持就用UTF-8编码,否则就使用本地编码(GBK).
15             if(FTPReply.isPositiveCompletion(ftpClient.sendCommand("OPTS UTF8", "ON"))) {
16                 LOCAL_CHARSET = "UTF-8";
17             }
18             ftpClient.setControlEncoding(LOCAL_CHARSET);
19             
20             String orginPath = ftpClient.printWorkingDirectory();
21             for(String subDir : subDirs){
22                 //encoding
23                 String strSubDir = new String(subDir.getBytes(LOCAL_CHARSET),SERVER_CHARSET);
24                 tmpMkdirs = ftpClient.makeDirectory(strSubDir);
25                 boolean tmpDoCommand = ftpClient.sendSiteCommand("chmod 755 " + strSubDir);
26                 ftpClient.changeWorkingDirectory(strSubDir);
27                 success = success || tmpMkdirs;
28             }
29             //ftpClient.changeWorkingDirectory(orginPath);
30         } catch (IOException e) {
31             // TODO Auto-generated catch block
32             e.printStackTrace();
33         }
34         return success;
35     }

 

  ==============================================

三、apache2服务器

  上面说到了basePath还记得不,由于项目需求,要从搭建的FTP服务器上面读取数据,就干脆弄了个apache服务器,用来将FTP的目录发布出来,供其他项目共享,而这个basePath就是共享目录的目录名,记得加"/"哈。

  搭建apache服务器的具体细节请参看我的另一篇博文 Ubuntu下搭建apache服务器

posted @ 2015-04-27 16:44  ShuolBDe  阅读(18305)  评论(1编辑  收藏  举报