1. FTPClient封装了从FTP服务器存储和检索文件所需的所有功能。 该类负责处理与FTP服务器交互的所有低级细节,并提供方便的更高级别接口。 与从SocketClient派生的所有类一样,您必须首先使用connect连接到服务器,然后再执行任何操作,最后在完成与服务器的交互后断开连接。 然后,您需要检查FTP回复代码以查看连接是否成功。
public class FTPClient extends FTP implements Configurable{
FTPClient ftp = new FTPClient();
FTPClientConfig config = new FTPClientConfig();
config.setXXX(YYY); // change required options
// for example config.setServerTimeZoneId("Pacific/Pitcairn")
ftp.configure(config );
boolean error = false;
try {
int reply;
String server = "ftp.example.com";
ftp.connect(server);
System.out.println("Connected to " + server + ".");
System.out.print(ftp.getReplyString());
// After connection attempt, you should check the reply code to verify
// success.
reply = ftp.getReplyCode();
if(!FTPReply.isPositiveCompletion(reply)) {
ftp.disconnect();
System.err.println("FTP server refused connection.");
System.exit(1);
}
... // transfer files
ftp.logout();
} catch(IOException e) {
error = true;
e.printStackTrace();
} finally {
if(ftp.isConnected()) {
try {
ftp.disconnect();
} catch(IOException ioe) {
// do nothing
}
}
System.exit(error ? 1 : 0);
}
}
2. 连接后,您需要立即检查答复代码(因为连接类型为void)。 FTPClient中所有FTP命令方法的约定是它们返回一个布尔值或一些其他值。 布尔方法在来自FTP服务器的成功完成答复时返回true,在答复时返回false,从而导致错误条件或失败。 返回布尔值以外的值的方法返回包含FTP命令生成的更高级别数据的值,如果答复导致错误条件或失败,则返回null。 如果要访问导致成功或失败的确切FTP回复代码,则必须在成功或失败后调用getReplyCode.
FTP.NON_PRINT_TEXT_FORMAT,FTP.STREAM_TRANSFER_MODE和FTP.FILE_STRUCTURE是唯一受支持的格式,传输模式和文件结构。
由于不同平台上的套接字处理可能会有很大差异,因此FTPClient会在每次传输之前自动发出新的PORT(或EPRT)命令,要求服务器连接到客户端的数据端口。 这可确保在Windows,Unix和Macintosh平台上执行相同的无问题行为。 此外,它使程序员不必自己发布PORT(或EPRT)命令并处理与平台相关的问题。
此外,出于安全考虑,将验证与客户端的所有数据连接,以确保它们来自目标方(主机和端口)。如果数据连接是由意外的一方启动的,该命令将关闭套接字并抛出IOException。您可以使用setRemoteVerificationEnabled()禁用此行为。
如果客户端空闲时间超过给定时间段(通常为900秒),FTP服务器可能会选择提前关闭连接。 FTPClient类将在收到对命令的FTPReply.SERVICE_NOT_AVAILABLE响应时检测到过早的FTP服务器连接关闭。发生这种情况时,遇到该回复的FTP类方法将抛出FTPConnectionClosedException。 FTPConnectionClosedException是IOException的子类,因此不需要单独捕获,但是如果要单独捕获它,它的catch块必须出现在更通用的IOException catch块之前。遇到FTPConnectionClosedException时,必须断开与disconnect()的连接以正确清理FTPClient使用的系统资源。在断开连接之前,您可以使用getReplyCode,getReplyString和getReplyStrings检查上一个回复代码和文本。通过定期向服务器发送NOOP命令,可以在客户端空闲时避免服务器断开连接。
不是为每个方法单独列出,而是在这里提到每个与服务器通信并抛出IOException的方法也可以抛出MalformedServerReplyException,它是IOException的子类。当从服务器收到的回复与协议规范有足够的偏差时,将抛出MalformedServerReplyException,尽管尝试尽可能宽松,但它无法以有用的方式解释
3.列表API示例目录列表的分页和未分页示例均可用,如下所示:
未分页(整个列表)访问,使用自动检测可访问的解析器:
FTPClient f = new FTPClient();
f.connect(server);
f.login(username, password);
FTPFile[] files = f.listFiles(directory);
分页访问,使用自动检测无法访问的解析器。 initateListParsing的第一个参数中定义的类应该从org.apache.commons.net.FTPFileEntryParser派生:
FTPClient f = new FTPClient();
f.connect(server);
f.login(username, password);
FTPListParseEngine engine =
f.initiateListParsing("com.whatever.YourOwnParser", directory);
while (engine.hasNext()) {
FTPFile[] files = engine.getNext(25); // "page size" you want
//do whatever you want with these files, display them, etc.
//expensive FTPFile objects not created until needed.
}
分页访问,使用自动检测可访问的解析器:
FTPClient f = new FTPClient();
f.connect(server);
f.login(username, password);
FTPListParseEngine engine = f.initiateListParsing(directory);
while (engine.hasNext()) {
FTPFile[] files = engine.getNext(25); // "page size" you want
//do whatever you want with these files, display them, etc.
//expensive FTPFile objects not created until needed.
}
请注意:这不适用于用户负责编写或读取数据流的方法,即retrieveFileStream(String),storeFileStream(String)和其他xxxFileStream方法
在文件传输期间,数据连接正忙,但控制连接处于空闲状态。 FTP服务器知道控制连接正在使用中,因此不会因缺少活动而关闭它,但是网络路由器要知道控制和数据连接是否相互关联起来要困难得多。某些路由器可能将控制连接视为空闲,如果通过数据连接的传输花费的时间超过路由器允许的空闲时间,则将其断开。
对此的一个解决方案是在控制连接上发送安全命令(即NOOP)以重置路由器的空闲计时器。这启用如下:
ftpClient.setControlKeepAliveTimeout(300); //将超时设置为5分钟
这将导致文件上载/下载方法大约每5分钟发送一次NOOP。以下公共方法支持此:
retrieveFile(String, OutputStream)
appendFile(String, InputStream)
storeFile(String, InputStream)
storeUniqueFile(InputStream)
storeUniqueFileStream(String)
该实现当前使用CopyStreamListener,该方法传递给Util.copyStream(InputStream,OutputStream,int,long,CopyStreamListener,boolean)方法,因此时序部分取决于每个块传输所需的时间。