The class FTPClient of the Apache Commons Library encapsulates FTP commands and provides convenient FTP support. To upload a file, your code will probably be like this (error handling ignored):
FTPClient ftp= new FTPClient();
ftp.connect(server, port);
ftp.login(username, password);
ftp.storeFile(remote, input);
where remote
is the file name on the remote computer, and input
is an InputStream.
So far so good, but suppose you need the file name (remote
) to be encoded by a certain convention, say UTF-8, which is not your default encoding. How to do that? You may notice the method FTPClient.setControlEncoding(String)
, and do
FTPClient ftp= new FTPClient();
ftp.connect(server, port);
ftp.login(username, password);
ftp.setControlEncoding("UTF-8");
ftp.storeFile(remote, input);
Unfortuantely, that does not work. Why?
It turns out that controlEncoding
is only used when the connection is established, and, after the client is connected to the remote node, although you can call setControlEncoding
, it does not change anything in your current connection. Therefore, we have to do ftp.setControlEncoding("UTF-8");
before ftp.connect;
, like this:
FTPClient ftp= new FTPClient();
ftp.setControlEncoding("UTF-8");
ftp.connect(server, port);
ftp.login(username, password);
ftp.storeFile(remote, input);
And now it works fine, the name of the file you create on the remote node is UTF-8 encoded.
The idea of the inventors of this class seems to be clear (see also source code): on calling connect
, an OutputStream
is created (using controlEncoding
), and this stream is used in the control connection to the FTP server. If the encoding is changed after the connection (hence the output stream) is created, it remains effectless.
The question is, however, why the API does provide two methods that are tightly coupled and have to be called in a certain order. Why not just strike the setter, and give connect
another parameter? This way, the user would not even have a chance to make the mistake as in our first listing!