最近用空闲时间做了一个ftp 的文件上传和下载的工程用于程序发布, 使用了 edtftpj.jar包, 版本是Version 3.1.2.
分别在 操作系统为 windowXP 和 solaris 的机器上面安装ftp 服务器, 进行测试.(这是我自己的测试环境, 所以有可能下面讲的东西跟您自己测试的有区别, 如果是这样还请多谅解)
主要操作的类继承于 FileTransferClient, 传输模式是Binary, 数据连接是 pasv(被动的)
可能使用的 edtftpj 是免费版的吧, 所以有些功能, 如判断是否文件, 是否文件夹的方法, 判断文件(夹)存在的方法都没有.
在开发过程中, 我发现同样的操作在 XP 或 solaris 系统上是有区别的.
如 directoryList 方法, 如果服务器为 XP系统, 那么 directoryList (不存在的文件(夹)) 会抛出异常;
但是服务器为 solaris系统 则不会抛出异常, 而是返回一个空的 FTPFile 数组, 并且如果 directoryList (空文件夹) 也是返回一个空的 FTPFile 数组, 这样就不能知道结果是 空文件夹 还是 不存在的文件(夹) 了(不要告诉我通过 *.*, 这样判断, 因为文件夹命可以用 '.' 的).
还有个更奇怪的问题, 服务器为 solaris, 用exists(.class文件) 判断.class 文件是否存在是不行的. 但是对于其他文件, 如jsp, html , xml 等都是可以 exists 方法判断是否存在.
对于这些情况, 通过网上搜索和查看 edtftpj 的源代码后, 我重写了 downloadFile 和 uploadFile, 新增了 downloadDir, uploadDir ,
isExist, isHasSize, createDir, isDirectory, isFile 等方法.
- downloadFile(String localFilePath, String remoteFilePath) //下载方法
如果 localFilePath = "C:/aa/cc//dd.txt//", 要先把多余的 "//" 去掉. 再看C 盘下面是否有文件夹aa/cc 存在, 没有则创建之, 然后就可以调用 父类 的downloadFile 方法了. (对于remoteFilePath 文件是否存在在外部判断)
- uploadFile(String localFilePath, String remoteFilePath) //上传方法
如果 remoteFilePath = "/ftp/aa//cc/dd.txt//", 要先把多余的 "//" 去掉, 取 "/ftp/aa//cc/", createDir("/ftp/aa//cc/"), 然后就可以调用 父类 的uploadFile 方法了. (对于localFilePath 文件是否存在在外部判断)
- downloadDir(String localDir,String remoteDir) //下载文件夹, 递归方法
如果 remoteDir = "/ftp/aa//cc/", 读取cc 文件夹下面的文件, 如果cc 为空文件夹, 创建localDir; 遍历cc 下面的文件(夹), 如果为文件, 调用 downloadFile(localDir + fileName, remoteDir + fileName), 如果为文件夹, 调用 downloadDir(localDir + fileName, remoteDir + fileName); (在外部判断 remoteDir 是否存在).
- uploadDir(String localDir, String remoteDir) //上传文件夹, 递归方法
如果 remoteDir = "/ftp/aa//cc/", 用 createDir(remoteDir) 创建, 遍历localDir 下面的文件, 如果为文件, 调用 uploadFile(localDir + fileName, remoteDir + fileName), 如果为文件夹, 调用 uploadDir(localDir + fileName, remoteDir + fileName);(在外部判断 localDir 是否存在)
- isExist(String remoteFilePath) //判断ftp 文件(夹) 是否存在
用 directoryNameList(remoteFilePath, false) 取文件列表. 如果前面的操作抛出异常, 那么证明文件(夹) 不存在; 如果文件列表数量大于或等于1, 证明文件(夹)存在; 如果文件列表数量等于0, 可能为空文件夹或者文件(夹) 不存在, 用 changeDirectory(remoteFilePath) 判断之, 操作抛出异常, 证明文件(夹)不存在, 反之证明存在是空文件夹; 其他情况视为文件(夹) 不存在;
- isHasSize(String remoteFilePath) //通过size 判断文件, 有大小就是文件, 这是针对服务器为 solaris 系统 的,
//因为 size 命令不是ftp 的标准命令, 有些 ftp 服务器可能不支持.
发送size remoteFilePath 命令, 如果返回结果为 '2' 开头的, 表示成功返回大小, remoteFilePath 为文件, 反之非文件; 抛出异常当非文件处理.
- createDir(String remoteDir) //创建远程文件夹
用 changeDirectory(remoteDir), 尝试进入该ftp文件夹, 如果抛出异常, 不能进入该文件夹, 证明文件夹不存在, 用createDirectory(remoteDir); 创建之;
- isDirectory(String remoteFilePath) //判断是否文件夹
用 isExist(remoteFilePath) 判断是否存在, 不存在返回false; 再用 exists(remoteFilePath) 判断是否是文件, 如果是, 返回false, 反之返回true; (如果服务器为 solaris 系统, 并且为.class 文件, exists(remoteFilePath) 不正确, 所以都是以 isFile 判断先, 因为基本上都是传输文件多. 可以把 isExist() 方法放在外部判断, 这样就减少了判断文件, 判断文件夹, 还有下载和上传都要判断文件(夹)是否存在, 这也是为什么上面很多方法都把判断文件(夹) 是否存在放在外部. 当然也可以对每个方法加个标识参数, 并且每个方法加多一个重载方法)
- isFile(String remoteFilePath) //判断是否文件
用 isExist(remoteFilePath) 判断是否存在, 不存在返回false; 再返回 isHasSize(remoteFilePath) 的结果.
基本就是这样啦, 把 判断文件(夹)是否存在 放在外部 是不想出现一个操作多次判断文件(夹) 是否存在.