如何使用Java FTP客户端?

如何使用Java FTP客户端?

Java FTP客户端库回顾

了解可用的库是和进行互相比较

摘要

本文解释了如何利用库用Java语言编写FTP客户端代码。它比较了FTP库的一个完全列表,演示了每个库的优点和缺点,并且帮助决策者为他们的需要选择适当的库。另外,本文阐述了Fa?ade模式如何在取代一个库时改变管理。最后,作者Jean-Pierre Norguet讨论并解决了由于缺乏权威性的说明书引起的一些问题。

让我们假设一个情景:我们要编写一个纯Java应用程序,该程序必须从运行FTP服务器的远程计算机上下载文件。我们也通过远程文件信息,像名字、日期、或者尺寸,来过滤下载。

自己来写一个FTP协议处理,尽管是有可能,并且可能很有趣。但是这样做也有可能有困难、花费长时间、并且有潜在的风险。既然我们不肯花费时间、精力、或者金钱自己来写一个处理器,那我们推荐使用一个可重用的现有的软件组件。万维网上有并且大量的库可供使用。有了一个FTP客户端库,下载一个文件用Java语言编写就像下面一样简单:

FTPClient ftpClient = new FTPClient();

ftpClient.connect("ftp.foo.com", "user01", "pass1234");

ftpClient.download("C://Temp//", "README.txt");

// Eventually other operations here ...

ftpClient.disconnect();

寻找一个适合我们需要的高质量的Java FTP客户端库并不像他看起来那么简单;它可能相当困难。要找到一个Java FTP客户端库需要花一些时间。接着,在我们找到所有的已存在的库之后,我们选哪个?每个库适合不同的需要。库在质量上是不等的,并且它们的设计有本质的区别。每个提供一套不同的属性和使用不同类型的行话来描述他们。

因此,计算和比较FTP客户端库证明是困难而且令人迷惑的。重复使用已存在的组件是一个值得推荐的过程,但在这个例子中,启动它也是令人沮丧的。并且这有点羞愧:在选好的一个好的FTP库之后,剩下的工作就是例程了。

本文旨在使选择过程简短、容易、并且有价值。我首先列出了所有的FTP客户端库。接着,我定义和描述了库应该用某种方式找到的相关标准的一个表格。最后,我列出了一个总浏览的矩阵,该矩阵给出了库间相互比较的过程的快速浏览。所有的信息提供了我们作出一个迅速、可靠、和长期的决定所需的每件事。

使用JDKJava 开发工具集)的FTP支持

用于FTP的访问规范是用于注释的请求:959RFC959)。Sun Microsystems提供了JDK的一个RFC959执行。但是它是内部的、非文档化的、并且不提供任何资源。当RFC959在尚未公开时,它实际上是执行RFC1738URL规范的一个公共界面的后终端。如图1

如何使用Java FTP客户端?

1. 使用JDKFTP支持。

RFC1738的一个执行过程在JDK中作为标准给出。它为基本的FTP传送做一个可推理的工作。它是公共的、文档化的、并且提供源代码。要使用它,我们可编写下面语句:

URL url = new URL("ftp://user01:pass1234@ftp.foo.com/README.txt;type=i");

URLConnection urlc = url.openConnection();

InputStream is = urlc.getInputStream(); // To download

OutputStream os = urlc.getOutputStream(); // To upload

使用JDKFTP客户端严格的遵守标准推荐,但它有以下几个说明:

它从根本上区别于第三方的FTP客户端库;这些执行RFC959而不是RFC1738

RFC959用大多数的桌面FTP客户端工具执行。许多Java程序员使用这些工具连接到FTP服务器上。作为一个尝试,这些工具及有可能优先于类似的RFC959库。

URL URLConnection类只开放用于通讯的流。Sun库不为构造原始的FTP服务器响应成为像String File RemoteFile 或者 Calendar之类的更合用的Java对象而提供直接支持。所以我们不得不编写更多的代码,只是为了把数据写入一个文件中或者开始一个目录列表。

正像RFC17383.2部分解释的一样,"最优化"FTP URL在每个操作后要求关闭(控制)连接。这对于传送许多小文件是一种浪费、并且毫无效率。而且,作了特别限制FTP服务器可能把会这样一个通讯开销认为一个是恶毒的网络攻击或者滥用而拒绝提供进一步的服务。

最后,它缺乏几个有用的属性。

由于以上所有或者某种原因,可优先使用一个第三方的库。下面部分列出了可供选择的第三方的库。

库比较

下表中列出了我要比较的库。他们都遵守访问FTP规范。接下来,我提供了供应商名字和库名(用斜体字)。Resources包括到每个产品网站的链接。为了快速使用这些库,我也提到了其主要的FTP客户端类。

1. JScape iNet Factory: com.jscape.inet.ftp.Ftp

2. /n 软件, IP*Works: ipworks.Ftp

3. 企业分布式技术, Java FTP Client Library: om.enterprisedt.net.ftp.FTPClient

4. IBM alphaWorks, FTP Bean Suite: com.ibm.network.ftp.protocol.FTPProtocol

5. SourceForge, JFtp: net.sf.jftp.net.FtpConnection

6. The Jakarta Project, Jakarta Commons/Net: org.apache.commons.net.ftp.FTPClient

7. JavaShop JNetBeans: jshop.jnet.FTPClient

8. Sun, JDK: sun.net.ftp.FtpClient

9. Florent Cueto, JavaFTP API: com.cqs.ftp.FTP

10. Bea Petrovicova, jFTP: cz.dhl.ftp.Ftp

11. The Globus Project, Java CoG Kit: org.globus.io.ftp.FTPClient

注意:

在写这篇文章时,IBM正在评测在它的站点上提供alphaWorks FTP Bean Suite的适合性。现在,下载对所有用户关闭。

Jakarta Commons/Net是代替了Savarese NetComponentsSavarese NetComponents将不会再被发展。

JavaShop JnetBeans好像已经废弃不用了。在写这篇文章时,站点已经离线一个多月了,并且我没有收到对我支持请求的任何响应。

标准

至此,我已经介绍并列出了可用的库。现在,我列出针对于要求评估的每个库的相关标准。我对于每一个标准量化了可能值,和在最后比较矩阵中使用的缩写(粗体)放在一起。

产品支持

库通过产品文档、编译的Java文档、样品代码和一个包括注释和解释的应用程序范例给用户提供支持。附加的支持可通过论坛、邮件列表、一个联系的email地址、或者一个在线故障追踪系统提供给用户。/n软件提供附加的支持是要另外收费的。

一个支持管理员的目的是快速支持的一个重要因素。支持管理员可以是:

一个志愿者(I

一个志愿小组(G

一个付费的专家团体提供支持(P

许可证

对于商业项目来说,产品许可证是从一开始就要考虑的一件重要的事。一些库可以自由的重用在商业产品中,但另一些就不能。GPL(GNU通用公共许可证)是一个强大的、有条件的许可证,然而Apache Software许可证只要求在重用的产品中说明一下。

商业许可证限制了利用库开发工作站编程的数目,但是不限制库本身的分布。

对于非商业的项目来说,许可证更像一个哲学问题,一个免费产品是令人感激的。

许可证可以是:

商业(C

GPL(G)

免费(F;但是,得检测一个免费许可证的限制条件。

一些库供应商要求提供备选的、限制较少的许可证。

提供的源代码

一个封闭源代码的,黑-盒子的软件库可能是使人生气的。由于下面的原因,提供源代码会让他更方便使用:

当应用程序代码执行出现故障时,进入库代码资源可帮助你理解库的行为。

源代码包含有用的注释

源代码可迅速的调整,以便适应新的需要

示范的源代码可以检测

寿命

库从他们首次公开发行时已经被测试、修复故障和支持。由于版本数在库中变化。我以最早的公开发行年的该标准为基准。

目录列表支持

检索来自服务器的远程文件信息(名称、尺寸、日期)在多数应用程序中是重要的。FTP协议提供NLST指令检索到文件名;NLST命名被精确的设计以便程序调用。LIST命令提供更多的文件信息;像RFC959注释的那样:"由于文件上的信息可能从系统到系统的广泛的不一致,该信息难以在一个程序中自动使用,但是对于人类用户来说相当有用。"没有其他标准方法检索文件信息;因此,客户端库试图调用LIST响应。但是,这可不是一件容易的事情:既然没有权威性的推荐可用于LIST相应格式,FTP服务器采用了不同的格式:

Unix类型:drwxr-xr-x 1 user01 ftp 512 Jan 29 23:32 prog

备选的Unix类型:drwxr-xr-x 1 user01 ftp 512 Jan 29 1997 prog

备选的Unix类型:drwxr-xr-x 1 1 1 512 Jan 29 23:32 prog

使用Unix类型的符号链接:lrwxr-xr-x 1 user01 ftp 512 Jan 29 23:32 prog -> prog2000

Weird Unix类型(用户和小组之间无间距):drwxr-xr-x 1 usernameftp 512 Jan 29 23:32 prog

MS-DOS类型:01-29-97 11:32PM <DIR> prog

Macintosh类型:drwxr-xr-x folder 0 Jan 29 23:32 prog

OS/2类型:0 DIR 01-29-97 23:32 PROG

Unix类型,其次是MS-DOS类型,是使用最广的格式。

Java FTP客户端库试图理解和自动检测尽可能多的格式。另外,他们提供用于处理不可预知的格式应答的不同备选项:

一个附加的方法,返回作为一个字符串的原始FTP响应(S

一个附加的方法,返回原始字符串集,每行/文件一个字符串(C

一个支持可插剖析器的框架(P

大多数的库捕捉LIST响应并将原始文件信息组织成Java 对象,例如:有了JScape iNet库,下列代码检索并且调用收到的文件信息到一个目录列表中:

java.util.Enumeration files = ftpClient.getDirListing();

while (files.hasMoreElements()) {

FtpFile ftpFile = (FtpFile) files.nextElement();

System.out.println(ftpFile.getFilename());

System.out.println(ftpFile.getFilesize());

// etc. other helpful methods are detailed in Javadoc

}

"遗留问题解答"部分将进一步讨论目录列表。

时间标签检索

在许多情况下,我们对一个远程文件的最近的修改的时间标签感兴趣。不幸的是,没有RFC介绍检索该信息的一个标准FTP命令。下面有两个实用的方法:

1. 通过捕捉服务器回答从LIST响应中检索该信息。但是,正像你在前面部分学到的一样,LIST响应在FTP服务器中各不相同,并且时间标签信息有时还不完整。使用Unix格式,当远程文件存在一年以上时会存在不精确性:只有日期和年份,没有小时或者分钟部分。

2. 使用非标准的MDTM命令。该命令专门检索一个远程文件的最新修改的时间标签。可惜,不是所有的FTP服务器都执行这个命令。

MDTM命令的一个复杂的备选项支持就是发送一条原始的MDTM命令并且捕捉命令。多数库提供发送一条原始的FTP命令的一个方法,像:

String timeStampString = ftpClient.command("MDTM README.txt");

另一个可能的方面就是FTP服务启用GMT(格林威治标准时间)返回时间信息。如果已知服务器时区与FTP通讯分离的话,那么java.util.TimeZone.getOffset()函数能帮助调整时区之间的差别。进一步了解该函数的信息请查看JDK文档。

"遗留问题解答"部分进一步讨论文件时间标签检索。

防火墙

典型的,防火墙设置在一个私人的企业网络和公共网络,如因特网,之间。它可管理从私人网络到公共网络的访问,但是从公共网络到私人网络的访问被否决。

Socks是一个作为因特网防火墙网关使用而开发的公共的、合用的协议。JDK支持Socks 4 Socks 5代理。他们由库中的某些部分控制。作为备选项,JVM命令行可设置Socks 代理参数:java -DsocksProxyPort=1080 -DsocksProxyHost=socks.foo.com -Djava.net.socks.username=user01 -Djava.net.socks.password=pass1234 ...

另一个通用的Socks 代理支持备选项是"Socks "客户端设备在下面的TCP/IP层。

JDK也支持HTTP通道,这些广泛使用的代理不允许FTP上传。/n软件的IP*Works允许你设置HTTP通道参数。

多数库既支持活跃的、也支持被动的连接:当客户端在接受引入的连接到更高的端口的防火墙后面时,被动连接有用。RFC1579更详细的讨论了这个友好的防火墙功能性。一些产品的文件把活跃和被动的链接分别看作PORT PASV命令。

并行传送

在一个桌面应用程序中,当在主单线程中的传送启动时,一切事情都冻结了。一些库自动的服务于在单独的线上并行传送的事件循环,因此我们不必创建和管理我们自己的线程。

JavaBean说明书支持

一些库实现JavaBean说明书。JavaBean默认允许可视的编程,它在主要的Java IDE中特征化。

/n软件的IP*WorksJavaBean设计是基于事件的(例如:ipworks.Ftp.listDirectory()函数)。尽管它保持同步并且相当安全,一些程序员还是发现它在服务器端的应用程序显得多余或者笨拙。

进程监督

一些库执行进程监督。进程监督支持使得执行追踪任何FTP传送的进程的事件监听器更为容易。 当开发一个友好的用户界面时,这个特征会有用。

传输类型

RFC959 3.1.1部分定义了几种传输类型,其中两个是常见的ASCII nonprint (默认) image (也称 binary)。有些库可根据文件扩展用自动模式设置,这样一种方法在现代信息系统很少有用,另一种传输类型已经废弃了并且不被任何一种Java支持。

其他标准说明

所有的库至少要在JDK 1.2.x或者更新的版本上运行;多数应该在JDK 1.1.x上运行,甚至是JDK 1.0.x

所有库是纯Java语言的。

比较矩阵列出了其他明显的标准。

Java FTP客户端库:比较矩阵

现在出现的是最后的比较矩阵。它在左边列的是标准,顶上列的是库,它列出了与左边标准对应的在上面的库。在单元中,Y表示"