Requirements: ftp4j Javadocs

You might also like

Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 12

Requirements

To run the ftp4j library you need a Java Runtime Environment J2SE v. 1.4 or later.

Installation
Add the ftp4j JAR file to your application classpath, and you'll be automatically enabled to
the use of the ftp4j classes.

Javadocs
Here come the ftp4j javadocs.

Quickstart
The main class of the library is FTPClient (it.sauronsoftware.ftp4j.FTPClient).

Start creating a FTPClient instance:

FTPClient client = new FTPClient();

Connect now to a remote FTP service:

client.connect("ftp.host.com");

If the service port is other than the standard 21 (or 990 if FTPS):

client.connect("ftp.host.com", port);

In example:

client.connect("ftp.host.com", 8021);

Step now to the login procedure:

client.login("carlo", "mypassword");

If no exception is thrown you are now authenticated to the remote server. Otherwise, if the
authentication attempt fails, you receive a it.sauronsoftware.ftp4j.FTPException.

Anonymous authentication, if admitted by the connected service, can be done sending the
username "anonymous" and an arbitrary password (note that some servers require an e-mail
address in place of the password):

client.login("anonymous", "ftp4j");

Do anything you want with the remote FTP service, then disconnect:

client.disconnect(true);
This one sends the FTP QUIT command to the remote server, requesting a legal disconnect
procedure. If you just want to break the connection, without sending any advice to the server,
call:

client.disconnect(false);

Connecting through a proxy


The client connects to the server through a connector (an object implementing the
it.sauronsoftware.ftp4j.FTPConnector interface), which returns to the client an already open
connection (an object implementing the it.sauronsoftware.ftp4j.FTPConnection interface).
That is why ftp4j could support a large set of proxies.

The connector for a client instance can be setted with the setConnector() method, obviously
before connecting the remote server:

client.setConnector(anyConnectorYouWant);

The default connector, which is used if no other is setted, is DirectConnector


(it.sauronsoftware.ftp4j.connectors.DirectConnector), which performs a direct connection to
the remote server, without asking the connection to any proxy.

If you can connect the remote server only through a proxy, the ftp4j library let you choose
between some other connectors:

 HTTPTunnelConnector (it.sauronsoftware.ftp4j.connectors.HTTPTunnelConnector)
This one can connect through a HTTP proxy which supports and permits the
CONNECT method.
 FTPProxyConnector (it.sauronsoftware.ftp4j.connectors.FTPProxyConnector)
This one can connect through a FTP proxy, supporting both the SITE and the OPEN
command style for demanding the connection with the remote host. Other kinds of
FTP proxies, such the ones requiring a username@remotehost authentication, can be
used without a specific connector, since they have been intended to be transparent to
the client.
 SOCKS4Connector (it.sauronsoftware.ftp4j.connectors.SOCKS4Connector)
This one can connect through a SOCKS 4/4a proxy.
 SOCKS5Connector (it.sauronsoftware.ftp4j.connectors.SOCKS5Connector)
This one can connect through a SOCKS 5 proxy.

Since the connector architecture used by ftp4j is a pluggable one, you can always build your
own connector implementing the FTPConnector interface.

FTPS/FTPES secured connection


The ftp4j library supports both FTPS (FTP over implicit TLS/SSL) and FTPES (FTP over
explicit TLS/SSL).

The setSecurity() method can be used to turn on the feature:


client.setSecurity(FTPClient.SECURITY_FTPS); // enables FTPS
client.setSecurity(FTPClient.SECURITY_FTPES); // enables FTPES

Both methods must be called before connecting the remote server.

If the security is set to SECURITY_FTPS, the default port used by the connect() method
changes to 990.

The client object, by default, negotiates SSL connections using the SSL socket factory
provided by javax.net.ssl.SSLSocketFactory.getDefault(). The default socket factory can be
changed calling the client setSSLSocketFactory() method. An alternative SSLSocketFactory,
for example, can be used to trust every certificate given by the remote host (use it carefully):

import it.sauronsoftware.ftp4j.FTPClient;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

// ...

TrustManager[] trustManager = new TrustManager[] { new X509TrustManager() {


public X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(X509Certificate[] certs, String
authType) {
}
public void checkServerTrusted(X509Certificate[] certs, String
authType) {
}
} };
SSLContext sslContext = null;
try {
sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustManager, new SecureRandom());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
}
SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
FTPClient client = new FTPClient();
client.setSSLSocketFactory(sslSocketFactory);
client.setSecurity(FTPClient.SECURITY_FTPS); // or
client.setSecurity(FTPClient.SECURITY_FTPES);

// ...

Browsing the remote site


Get the current directory absolute path calling:
String dir = client.currentDirectory();

Change directory with:

client.changeDirectory(newPath);

You can use both absolute and relative paths:

client.changeDirectory("/an/absolute/one");
client.changeDirectory("relative");

Back to the parent directory with:

client.changeDirectoryUp();

Renaming files and directories


To rename a remote file or directory:

client.rename("oldname", "newname");

Moving files and directories


The rename() method can also be used to move files and directories from a location to
another.

In example, think in the current working directory you have a file called "myfile.txt", and you
want to move it in the sub-directory "myfolder":

client.rename("myfile.txt", "myfolder/myfile.txt");

Deleting files
To delete a remote file call:

client.deleteFile(relativeOrAbsolutePath);

In example:

client.deleteFile("useless.txt");

Creating and deleting directories


You can create a new directory on the remote site, if the service gives you this oppurtunity:

client.createDirectory("newfolder");

You can also remove an existing one:

client.deleteDirectory(absoluteOrRelativePath);
In example:

client.deleteDirectory("oldfolder");

Please note that usually FTP servers can delete only empty directories.

Listing files, directories and links


The FTP protocol doesn't offer a wide supported method to get complete informations about
the contents of the working directory. The LIST command usually gives all you need to
know, but unfortunately every server can use a different style for the response. It means that
some servers return a UNIX style directory listing, some servers prefer the DOS style, others
use some alternative ones.

The ftp4j library can handle many LIST response formats, building from them a unified
structured object representation of the directory contents. Currently ftp4j can handle:

 UNIX style and variants (i.e. MAC style)


 DOS style
 NetWare styles
 EPLF
 MLSD

This is done using pluggable parsers. The package it.sauronsoftware.ftp4j.listparsers contains


the ones handling the styles listed above. Most of the time this should be enough.

To list the current working directory entries call:

FTPFile[] list = client.list();

If you receive a FTPListParseException (it.sauronsoftware.ftp4j.FTPListParseException) it


means that the server has replied to the LIST command in an incomprehensible style, that is
none of the ones listed above. So you can try with the listNames() method, but that is less
profitable than the list() one. Extremis malis extrema remedia: build your own LIST response
parser, supporting the style you have encountered. You can do that implementing the
FTPListParser (it.sauronsoftware.ftp4j.FTPListParser) interface. Then you can plug an
instance of your parser in the client calling the addListParser() method.

FTPFile (it.sauronsoftware.ftp4j.FTPFile) objects offer a representation of the directory


contents, including files, sub-directories and links. Depending on the response supplied by
the server, some fields of a FTPFile object could be null or setted to non-sense values. Please
check the javadocs for details.

You can also use a file filter parameter with the list() method, i.e.:

FTPFile[] list = client.list("*.jpg");

If the connected server declares explicitly to support the special MLSD command, ftp4j will
use it instead of the basic LIST command. MLSD responses, infact, are standard, accurated
and more easily parsable. Unfortunately not all of the servers support this command, and
some of them support it badly. For these reasons the developer can control whether ftp4j
should use the MLSD command by calling the setMLSDPolicy() method of a FTPClient
object. Admitted values are:

 FTPClient.MLSD_IF_SUPPORTED
The client will use the MLSD command (instead of LIST) only if the server declares
explicitly its support. This is the default ftp4j behaviour.
 FTPClient.MLSD_ALWAYS
The client will always use the MLSD command (instead of LIST), also if it is not
explicitly supported by the server.
 FTPClient.MLSD_NEVER
The client will never use the MLSD command (instead of LIST), also if it is explicitly
supported by the server.

For example:

client.setMLSDPolicy(FTPClient.MLSD_NEVER);

Getting the modification date of files and directories


Usually a FTPFile object tells you about the last modification date of an entry, but as
described above, that depends on the reply sent by the server. If you need a modification date
and you can't get it through the list() method, try this:

java.util.Date md = client.modifiedDate("filename.ext");

Downloading and uploading files


The easiest way to download a remote file is a call to the download(String, File) method:

client.download("remoteFile.ext", new java.io.File("localFile.ext"));

To upload:

client.upload(new java.io.File("localFile.ext"));

These are blocking calls: they will return only when the transfer will be completed (or failed,
or aborted). Moreover a synchronization lock is imposed on the client, since only a transfer
per time is permitted in a regular FTP communication. You can handle multiple transfers per
time using several FTPClient objects, each one establishing a separate connection with the
server.

You can monitor transfers with FTPDataTransferListener


(it.sauronsoftware.ftp4j.FTPDataTransferListener) objects. Implement your one:

import it.sauronsoftware.ftp4j.FTPDataTransferListener;

public class MyTransferListener implements FTPDataTransferListener {

public void started() {


// Transfer started
}

public void transferred(int length) {


// Yet other length bytes has been transferred since the
last time this
// method was called
}

public void completed() {


// Transfer completed
}

public void aborted() {


// Transfer aborted
}

public void failed() {


// Transfer failed
}

Now download or upload as follows:

client.download("remoteFile.ext", new java.io.File("localFile.ext"), new


MyTransferListener());
client.upload(new java.io.File("localFile.ext"), new MyTransferListener());

While the client is downloading or uploading, the transfer can be aborted by another thread
calling the abortCurrentDataTransfer() method on the same FTPClient object. This one
requires a boolean parameter: true to perform a legal abort procedure (an ABOR command is
sent to the server), false to abruptly close the transfer without advice:

client.abortCurrentDataTransfer(true); // Sends ABOR


client.abortCurrentDataTransfer(false); // Breaks abruptly

Note that also the list() and the listNames() methods imply a data transfer (the response is
served on a data transfer channel), so the abortCurrentDataTransfer() method can also be
used to interrupt a list procedure.

When a data tranfer is aborted the download(), upload(), list() and listNames() methods die
throwing a FTPAbortedException (it.sauronsoftware.ftp4j.FTPAbortedException).

Download and upload operation can be resumed suppling a restartAt parameter:

client.download("remoteFile.ext", new java.io.File("localFile.ext"), 1056);

This one resumes the download operation starting from the 1056th byte of the file. The first
byte transferred will be the 1057th.

Other download() and upload() variants let you work with streams instead of java.io.File
objects. So you can also transfer data from and to a database, a network connection or...
another FTPClient object!
Check the javadocs.

Active and passive data transfer modes


Data transfer channels are established through a separate network connection between the
client and the server. The server could be active or passive in the establishing of the transfer
channel. When the server is active data transfers work as follows:

1. The client sends to the server its IP address and a port number.
2. The client asks to the server a data transfer, and it starts listening the port sent before.
3. The server connects the address and the port supplied by the client.
4. The data transfer starts in the new established channel.

The active mode requires that your client could receive incoming connections from the
server. If your client is behind a firewall, a proxy, a gateway or a mix of them, most of the
time that is a problem, since it cannot receive incoming connections from outside. Here
comes the passive data transfer mode:

1. The client asks to the server to prepare a passive data transfer.


2. The server replies with its IP address and a port number.
3. The client asks the transfer and connects.
4. The data transfer starts in the new established channel.

In passive mode the client connects the server: no incoming connection is required.

With ftp4j you can switch between the active and passive modes calling:

client.setPassive(false); // Active mode


client.setPassive(true); // Passive mode

The default value for a ftp4j client passive flag is true: if you never call setPassive(false) your
client will act ever asking the passive mode to the server before every transfer.

In the passive transfer mode, the following system property can be set:

 ftp4j.passiveDataTransfer.useSuggestedAddress
Setting this property value to "true", "yes" or "1" (case insensitive) causes the client to
use the address suggested by the server as a positive reply to a PASV command. To
avoid frequently reported NAT problems, infact, ftp4j doesn't trust the IP address
declared by the server. The response to the the PASV command is used only for the
port information, while the address is replaced with the host name used for the initial
connection to the server. By activating this feature the developer can force ftp4j to
trust and use the address supplied by the server every time a passive data transfer is
being negotiated.

In the active transfer mode, the following system properties can be set:

 ftp4j.activeDataTransfer.hostAddress
Host address. The client will forward to the server the given address, when the server
is requested to perform a connection to the client. The value should be a valid IPv4
address in the a.b.c.d form. I.e. 178.12.34.167. If the value is not supplied, the client
resolves automatically the system address. But if the client runs in a LAN, connecting
an external server through a router with port-forwarding service for active data
transfers, the auto-detected address could not be the right one. This also should
happen when the system has more network interfaces. By using this system property
this kind of problems can be solved.
 ftp4j.activeDataTransfer.portRange
Connection port range. The client will pick a port in the range for the data transfer.
The value must be in the start-stop form. I.e. 6000-7000 means that the client will
pick ports only between the given interval when it will ask the server to perform a
connection. By default no range is specified: that means the client could pick any
available port.
 ftp4j.activeDataTransfer.acceptTimeout
A value in milliseconds that will be picked as the connection timeout. If the server
does not connect the client within the given timeout, the transfer is interrupted
throwing a FTPDataTransferException. A value equal to 0 means that no timeout will
be applied. Default value is 30000 (30 seconds).

To set a system property you can:

 Start the virtual machine with one or more -Dproperty=value arguments. I.e.:
 java -Dftp4j.activeDataTransfer.hostAddress=178.12.34.167
 -Dftp4j.activeDataTransfer.portRange=6000-7000
-Dftp4j.activeDataTransfer.acceptTimeout=5000 MyClass

 Set property values directly in the code. I.e.:


 System.setProperty("ftp4j.activeDataTransfer.hostAddress",
"178.12.34.167");
 System.setProperty("ftp4j.activeDataTransfer.portRange", "6000-
7000");
System.setProperty("ftp4j.activeDataTransfer.acceptTimeout", "5000");

Binary and textual data transfer types


Another data transfer key concept concerns the binary and the textual types. When a transfer
is binary the file is treated as a binary stream, and it is stored by the target machine as it is
received from the source. A textual data transfer, instead, treats the transferred file as a
character stream, performing charset transformation. Suppose your client is running on a
Windows platform, while the server runs on UNIX, whose default charsets are usually
different. The client send a file to the server selecting textual type. The client assumes that the
file is encoded with the machine standard charset, so it decodes every character and encodes
it in an intermediate charset before sending. The server receives the stream, decode the
intermediate charset and encodes the file with its machine default charset before storing.
Bytes has been changed, but contents are the same.

You can choose your transfer type calling:

client.setType(FTPClient.TYPE_TEXTUAL);
client.setType(FTPClient.TYPE_BINARY);
client.setType(FTPClient.TYPE_AUTO);
The TYPE_AUTO constant, which is also the default one, let the client pick the type
automatically: a textual transfer will be performed if the extension of the file is between the
ones the client recognizes as textual type markers. File extensions are sniffed through a
FTPTextualExtensionRecognizer (it.sauronsoftware.ftp4j.FTPTextualExtensionRecognizer)
instance. The default extension recognizer, which is an instance of
it.sauronsoftware.ftp4j.recognizers.DefaultTextualExtensionRecognizer, recognizes these
extensions as textual ones:

abc acgi aip asm asp c c cc cc com conf cpp


csh css cxx def el etx f f f77 f90 f90 flx
for for g h h hh hh hlb htc htm html htmls
htt htx idc jav jav java java js ksh list
log lsp lst lsx m m mar mcf p pas php pl pl
pm py rexx rt rt rtf rtx s scm scm sdml sgm
sgm sgml sgml sh shtml shtml spc ssi talk
tcl tcsh text tsv txt uil uni unis uri uris
uu uue vcs wml wmls wsc xml zsh

You can build your own recognizer implementing the FTPTextualExtensionRecognizer


interface, but maybe you'll like more to instance the convenience class
ParametricTextualExtensionRecognizer
(it.sauronsoftware.ftp4j.recognizers.ParametricTextualExtensionRecognizer). Anyway, don't
forget to plug your recognizer in the client:

client.setTextualExtensionRecognizer(myRecognizer);

Data transfer compression


Some servers support a data transfer compression feature called MODE Z. This feature is
useful to save bandwidth on large file transfers. Once the client is connected to the server and
authenticated, the compression support can be checked by calling:

boolean compressionSupported = client.isCompressionSupported();

If compression is supported on the server-side, it can be enabled by calling:

client.setCompressionEnabled(true);

After this call, any subsequent data transfer (downloads, uploads and list operations) will be
compressed, saving bandwidth.

Data transfer compression can be disabled again by calling:

client.setCompressionEnabled(false);

The flag value can also be checked:

boolean compressionEnabled = client.isCompressionEnabled();

Please note that compressed data transfer will take place only if compression is both
supported and enabled.
By default, compression is disabled, even if supported by the server. If required, it has to be
explicitly turned on.

NOOPing the server


Suppose your client is doing nothing since it's waiting for user input. Usually FTP servers
disconnect automatically an inactive client. To avoid this timeout you can send now and then
a NOOP command. This one does nothing but it points out to the server that the client is still
alive, resetting the timeout counter. Call:

client.noop();

Automatic NOOPs can also be issued by the client when an inactivity timeout occurs. By
default this feature is disabled. It can be enabled by setting the timeout duration with the
setAutoNoopTimeout() method, supplying a value expressed in milliseconds. For example:

client.setAutoNoopTimeout(30000);

With this value, the client will issue a NOOP command after 30 seconds of inactivity.

The automatic NOOP timeout can be disabled again by using a value equal or less than zero:

client.setAutoNoopTimeout(0);

Site specific and custom commands


You can send site specific commands as follows:

FTPReply reply = client.sendSiteCommand("YOUR COMMAND");

You can also sends custom commands:

FTPReply reply = client.sendCustomCommand("YOUR COMMAND");

Both sendSiteCommand() and sendCustomCommand() return a FTPReply


(it.sauronsoftware.ftp4j.FTPReply) object. With this one you can check the response
received, getting the server reply code and message. The FTPCodes
(it.sauronsoftware.ftp4j.FTPCodes) interface reports some common FTP reply codes, so you
can try to match your reply code with one of those the library knows for sure.

Exceptions handling
The ftp4j library defines five kinds of exception:

 FTPException (it.sauronsoftware.ftp4.FTPException)
Depending on the method, this one is thrown to report a FTP failure. You can check
the reported error code, testing it against the FTPCodes constants to gain more details
about the reason of the failure.
 FTPIllegalReplyException (it.sauronsoftware.ftp4.FTPIllegalReplyException)
This one means that the remote server has replied in an illegal way, that is not FTP
compliant. That should be very rare.
 FTPListParseException (it.sauronsoftware.ftp4.FTPListParseException)
This one is thrown by the list() method if the response sent by the server cannot be
parsed through the list parsers known by the client.
 FTPDataTransferException (it.sauronsoftware.ftp4.FTPDataTransferException)
This one is thrown if a data transfer (download, upload, but also list and listNames)
fails due to a network connection error.
 FTPAbortedException (it.sauronsoftware.ftp4.FTPAbortedException)
This one is thrown if a data transfer (download, upload, but also list and listNames)
fails due to a client abort request.

You might also like