FTPClient encapsulates all the functionality necessary to store and
retrieve files from an FTP server. This class takes care of all
low level details of interacting with an FTP server and provides
a convenient higher level interface. As with all classes derived
from SocketClient ,
you must first connect to the server with
connect
before doing anything, and finally
disconnect
after you're completely finished interacting with the server.
Then you need to check the FTP reply code to see if the connection
was successful. For example:
boolean error = false;
try {
int reply;
ftp.connect("ftp.foobar.com");
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);
}
Immediately after connecting is the only real time you need to check the
reply code (because connect is of type void). The convention for all the
FTP command methods in FTPClient is such that they either return a
boolean value or some other value.
The boolean methods return true on a successful completion reply from
the FTP server and false on a reply resulting in an error condition or
failure. The methods returning a value other than boolean return a value
containing the higher level data produced by the FTP command, or null if a
reply resulted in an error condition or failure. If you want to access
the exact FTP reply code causing a success or failure, you must call
getReplyCode after
a success or failure.
The default settings for FTPClient are for it to use
FTP.ASCII_FILE_TYPE ,
FTP.NON_PRINT_TEXT_FORMAT ,
FTP.STREAM_TRANSFER_MODE , and
FTP.FILE_STRUCTURE . The only file types directly supported
are FTP.ASCII_FILE_TYPE and
FTP.IMAGE_FILE_TYPE (which is the same as
FTP.BINARY_FILE_TYPE ). Because there are at lest 4
different EBCDIC encodings, we have opted not to provide direct support
for EBCDIC. To transfer EBCDIC and other unsupported file types you
must create your own filter InputStreams and OutputStreams and wrap
them around the streams returned or required by the FTPClient methods.
FTPClient uses the NetASCII
filter streams to provide transparent handling of ASCII files. We will
consider incorporating EBCDIC support if there is enough demand.
FTP.NON_PRINT_TEXT_FORMAT ,
FTP.STREAM_TRANSFER_MODE , and
FTP.FILE_STRUCTURE are the only supported formats,
transfer modes, and file structures.
Because the handling of sockets on different platforms can differ
significantly, the FTPClient automatically issues a new PORT command
prior to every transfer requiring that the server connect to the client's
data port. This ensures identical problem-free behavior on Windows, Unix,
and Macintosh platforms. Additionally, it relieves programmers from
having to issue the PORT command themselves and dealing with platform
dependent issues.
Additionally, for security purposes, all data connections to the
client are verified to ensure that they originated from the intended
party (host and port). If a data connection is initiated by an unexpected
party, the command will close the socket and throw an IOException. You
may disable this behavior with
setRemoteVerificationEnabled() .
You should keep in mind that the FTP server may choose to prematurely
close a connection if the client has been idle for longer than a
given time period (usually 900 seconds). The FTPClient class will detect a
premature FTP server connection closing when it receives a
FTPReply.SERVICE_NOT_AVAILABLE
response to a command.
When that occurs, the FTP class method encountering that reply will throw
an FTPConnectionClosedException
.
FTPConnectionClosedException
is a subclass of IOException and therefore need not be
caught separately, but if you are going to catch it separately, its
catch block must appear before the more general IOException
catch block. When you encounter an
FTPConnectionClosedException
, you must disconnect the connection with
disconnect() to properly clean up the
system resources used by FTPClient. Before disconnecting, you may check the
last reply code and text with
getReplyCode ,
getReplyString ,
and
getReplyStrings .
You may avoid server disconnections while the client is idle by
periodicaly sending NOOP commands to the server.
Rather than list it separately for each method, we mention here that
every method communicating with the server and throwing an IOException
can also throw a
MalformedServerReplyException
, which is a subclass
of IOException. A MalformedServerReplyException will be thrown when
the reply received from the server deviates enough from the protocol
specification that it cannot be interpreted in a useful manner despite
attempts to be as lenient as possible.
Listing API Examples
Both paged and unpaged examples of directory listings are available,
as follows:
Unpaged (whole list) access, using a parser accessible by auto-detect:
Paged access, using a parser not accessible by auto-detect. The class
defined in the first parameter of initateListParsing should be derived
from org.apache.commons.net.FTPFileEntryParser:
FTPClient f=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.
}
Paged access, using a parser accessible by auto-detect:
FTPClient f=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.
}
For examples of using FTPClient on servers whose directory listings
use languages other than English
use date formats other than the American English "standard" MM d yyyy
are in different timezones and you need accurate timestamps for dependency checking
as in Ant
boolean error = false; try { int reply; ftp.connect("ftp.foobar.com"); 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); }Immediately after connecting is the only real time you need to check the reply code (because connect is of type void). The convention for all the FTP command methods in FTPClient is such that they either return a boolean value or some other value. The boolean methods return true on a successful completion reply from the FTP server and false on a reply resulting in an error condition or failure. The methods returning a value other than boolean return a value containing the higher level data produced by the FTP command, or null if a reply resulted in an error condition or failure. If you want to access the exact FTP reply code causing a success or failure, you must call getReplyCode after a success or failure.
The default settings for FTPClient are for it to use
FTP.ASCII_FILE_TYPE,FTP.NON_PRINT_TEXT_FORMAT,FTP.STREAM_TRANSFER_MODE, andFTP.FILE_STRUCTURE. The only file types directly supported areFTP.ASCII_FILE_TYPEandFTP.IMAGE_FILE_TYPE(which is the same asFTP.BINARY_FILE_TYPE). Because there are at lest 4 different EBCDIC encodings, we have opted not to provide direct support for EBCDIC. To transfer EBCDIC and other unsupported file types you must create your own filter InputStreams and OutputStreams and wrap them around the streams returned or required by the FTPClient methods. FTPClient uses the NetASCII filter streams to provide transparent handling of ASCII files. We will consider incorporating EBCDIC support if there is enough demand.FTP.NON_PRINT_TEXT_FORMAT,FTP.STREAM_TRANSFER_MODE, andFTP.FILE_STRUCTUREare the only supported formats, transfer modes, and file structures.Because the handling of sockets on different platforms can differ significantly, the FTPClient automatically issues a new PORT command prior to every transfer requiring that the server connect to the client's data port. This ensures identical problem-free behavior on Windows, Unix, and Macintosh platforms. Additionally, it relieves programmers from having to issue the PORT command themselves and dealing with platform dependent issues.
Additionally, for security purposes, all data connections to the client are verified to ensure that they originated from the intended party (host and port). If a data connection is initiated by an unexpected party, the command will close the socket and throw an IOException. You may disable this behavior with setRemoteVerificationEnabled() .
You should keep in mind that the FTP server may choose to prematurely close a connection if the client has been idle for longer than a given time period (usually 900 seconds). The FTPClient class will detect a premature FTP server connection closing when it receives a FTPReply.SERVICE_NOT_AVAILABLE response to a command. When that occurs, the FTP class method encountering that reply will throw an FTPConnectionClosedException .
FTPConnectionClosedExceptionis a subclass ofIOExceptionand therefore need not be caught separately, but if you are going to catch it separately, its catch block must appear before the more generalIOExceptioncatch block. When you encounter an FTPConnectionClosedException , you must disconnect the connection with disconnect() to properly clean up the system resources used by FTPClient. Before disconnecting, you may check the last reply code and text with getReplyCode , getReplyString , and getReplyStrings . You may avoid server disconnections while the client is idle by periodicaly sending NOOP commands to the server.Rather than list it separately for each method, we mention here that every method communicating with the server and throwing an IOException can also throw a MalformedServerReplyException , which is a subclass of IOException. A MalformedServerReplyException will be thrown when the reply received from the server deviates enough from the protocol specification that it cannot be interpreted in a useful manner despite attempts to be as lenient as possible.
Listing API Examples Both paged and unpaged examples of directory listings are available, as follows:
Unpaged (whole list) access, using a parser accessible by auto-detect:
FTPClient f=FTPClient(); f.connect(server); f.login(username, password); FTPFile[] files = listFiles(directory);Paged access, using a parser not accessible by auto-detect. The class defined in the first parameter of initateListParsing should be derived from org.apache.commons.net.FTPFileEntryParser:
FTPClient f=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. }Paged access, using a parser accessible by auto-detect:
FTPClient f=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. }For examples of using FTPClient on servers whose directory listings
- use languages other than English
- use date formats other than the American English "standard"
- are in different timezones and you need accurate timestamps for dependency checking
as in Ant
see FTPClientConfig .MM d yyyyNOTE: If you experience problems with unwanted firing of
during periods of client inactivity, this can be alleviated by calling . For more details, see this thread.