zoukankan      html  css  js  c++  java
  • 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服务器

  • 相关阅读:
    开场白
    八皇后(DFS)
    function-paren-newline (Rules) – Eslint 中文开发手册
    Java面试题:Error和Exception有什么区别?
    Linux mmove 命令
    字母间距 | letter-spacing (Scalable Vector Graphics) – CSS 中文开发手册
    object.watch (Object) – JavaScript 中文开发手册
    ASP.NET MVC HTML 帮助器
    C 库函数 – strerror()
    Java中的初始化模块
  • 原文地址:https://www.cnblogs.com/ShuolBDe/p/4460612.html
Copyright © 2011-2022 走看看