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服务器

  • 相关阅读:
    Azure PowerShell (7) 使用CSV文件批量设置Virtual Machine Endpoint
    Windows Azure Cloud Service (39) 如何将现有Web应用迁移到Azure PaaS平台
    Azure China (7) 使用WebMetrix将Web Site发布至Azure China
    Microsoft Azure News(4) Azure新D系列虚拟机上线
    Windows Azure Cloud Service (38) 微软IaaS与PaaS比较
    Windows Azure Cloud Service (37) 浅谈Cloud Service
    Azure PowerShell (6) 设置单个Virtual Machine Endpoint
    Azure PowerShell (5) 使用Azure PowerShell创建简单的Azure虚拟机和Linux虚拟机
    功能代码(1)---通过Jquery来处理复选框
    案例1.用Ajax实现用户名的校验
  • 原文地址:https://www.cnblogs.com/ShuolBDe/p/4460612.html
Copyright © 2011-2022 走看看