Bibliotecas de cliente FTP de Java revisadas

Imaginemos una situación en la que queremos escribir una aplicación Java pura que debe descargar archivos desde una computadora remota que ejecuta un servidor FTP. También queremos filtrar las descargas en función de la información del archivo remoto, como el nombre, la fecha o el tamaño.

Aunque es posible, y quizás divertido, escribir un controlador de protocolo para FTP desde cero, hacerlo también es difícil, largo y potencialmente riesgoso. Como preferimos no gastar tiempo, esfuerzo o dinero escribiendo un controlador por nuestra cuenta, preferimos reutilizar un componente de software existente. Y hay muchas bibliotecas disponibles en la World Wide Web. Con una biblioteca de cliente FTP, la descarga de un archivo se puede escribir en Java tan simplemente como:

FTPClient ftpClient = new FTPClient (); ftpClient.connect ("ftp.foo.com", "user01", "pass1234"); ftpClient.download ("C: \\ Temp \\", "README.txt"); // Eventualmente otras operaciones aquí ... ftpClient.disconnect ();

Buscar una biblioteca cliente FTP de Java de calidad que se adapte a nuestras necesidades no es tan simple como parece; puede ser bastante doloroso. Se necesita algún tiempo para encontrar una biblioteca de cliente FTP de Java. Luego, después de encontrar todas las bibliotecas existentes, ¿cuál seleccionamos? Cada biblioteca aborda diferentes necesidades. Las bibliotecas son de calidad desigual y sus diseños difieren fundamentalmente. Cada uno ofrece un conjunto diferente de características y utiliza diferentes tipos de jerga para describirlas.

Por lo tanto, evaluar y comparar bibliotecas de cliente FTP puede resultar difícil y confuso. Reutilizar componentes existentes es un proceso encomiable, pero en este caso, comenzar puede ser desalentador. Y esto es una pena: después de elegir una buena biblioteca FTP, el resto es rutina.

Este artículo tiene como objetivo hacer que el proceso de selección sea breve, fácil y valioso. Primero enumero todas las bibliotecas de cliente FTP disponibles. Luego defino y describo una lista de criterios relevantes que las bibliotecas deberían abordar de alguna manera. Finalmente, presento una matriz de descripción general que brinda una vista rápida de cómo se comparan las bibliotecas entre sí. Toda esta información proporciona todo lo que necesitamos para tomar una decisión rápida, confiable y duradera.

Soporte FTP en JDK

La especificación de referencia para FTP es Solicitud de comentarios: 959 (RFC959). Sun Microsystems proporciona una implementación RFC959 en el JDK, pero es interna, no está documentada y no se proporciona ninguna fuente. Si bien RFC959 se encuentra en las sombras, en realidad es el back-end de una interfaz pública que implementa RFC1738, la especificación de URL, como se ilustra en la Figura 1.

Se ofrece una implementación de RFC1738 como estándar en el JDK. Hace un trabajo razonable para operaciones básicas de transferencia FTP. Es público y está documentado, y se proporciona el código fuente. Para usarlo, escribimos lo siguiente:

URL url = nueva URL ("ftp: // user01: [email protected]/README.txt; type = i"); URLConnection urlc = url.openConnection (); InputStream es = urlc.getInputStream (); // Para descargar OutputStream os = urlc.getOutputStream (); // Subir

El soporte del cliente FTP en JDK sigue estrictamente la recomendación estándar, pero tiene varias desventajas:

  • Se diferencia fundamentalmente de las bibliotecas cliente FTP de terceros; estos implementan RFC959 en lugar de RFC1738.
  • RFC959 se implementa en la mayoría de las herramientas de cliente FTP de escritorio. Muchos programadores de Java utilizan estas herramientas para conectarse a servidores FTP. Por una cuestión de gusto, estas herramientas probablemente prefieran bibliotecas similares a RFC959.
  • Las clases URLy URLConnectionsolo abren flujos para la comunicación. La biblioteca ofrece apoyo sin recta Sun para estructurar las respuestas del servidor FTP primas en más utilizable como objetos Java String, File, RemoteFile, o Calendar. Así que tenemos que escribir más código solo para escribir datos en un archivo o explotar una lista de directorios.
  • Como se explica en la sección 3.2.5 de RFC1738, "Optimización", las URL de FTP requieren que la conexión (de control) se cierre después de cada operación. Esto es un desperdicio y no es eficiente para transferir muchos archivos pequeños. Además, los servidores FTP extremadamente restrictivos pueden considerar esta sobrecarga de comunicación como un ataque o abuso de red maligno y negar el servicio adicional.
  • Finalmente, carece de varias funciones útiles.

Por todas o algunas de estas razones, es preferible utilizar una biblioteca de terceros. La siguiente sección enumera las alternativas de terceros disponibles.

Comparación de bibliotecas

La lista a continuación describe las bibliotecas que comparo a lo largo de este artículo. Todos siguen la especificación FTP de referencia. A continuación, menciono el nombre del proveedor y el nombre de la biblioteca (en cursiva). Los recursos incluyen enlaces al sitio web de cada producto. Para impulsar el uso de la biblioteca, también menciono la clase principal de cliente FTP.

  1. JScape, iNet Factory :com.jscape.inet.ftp.Ftp
  2. / n software, IP * Funciona :ipworks.Ftp
  3. Tecnologías distribuidas empresariales, biblioteca de cliente FTP de Java :com.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. El Proyecto Jakarta, Jakarta Commons / Net :org.apache.commons.net.ftp.FTPClient
  7. JavaShop JNetBeans :jshop.jnet.FTPClient
  8. Sol, JDK :sun.net.ftp.FtpClient
  9. Florent Cueto, API JavaFTP :com.cqs.ftp.FTP
  10. Bea Petrovicova, jFTP :cz.dhl.ftp.Ftp
  11. El Proyecto Globus, Java CoG Kit :org.globus.io.ftp.FTPClient

Notas:

  • En el momento de escribir este artículo, IBM está evaluando la conveniencia de ofrecer su alphaWorks FTP Bean Suite en su sitio web. Por ahora, la descarga está cerrada para todos los usuarios.
  • Jakarta Commons / Net es un reemplazo directo de Savarese NetComponents, que ya no se desarrolla.
  • JavaShop JNetBeans parece haber sido abandonado. En el momento de escribir este artículo, el sitio ha estado fuera de línea durante más de un mes y nunca recibí ninguna respuesta a mis solicitudes de soporte.

Criterios

Hasta ahora, presenté el contexto y enumeré las bibliotecas disponibles. Ahora, enumero los criterios relevantes con los que se evaluará cada biblioteca. Enumero los valores posibles para cada criterio, junto con la abreviatura (en negrita ) utilizada en la matriz de comparación final.

Soporte de producto

Las bibliotecas brindan soporte a los usuarios a través de la documentación del producto, Javadocs compilados, código de muestra y una aplicación de ejemplo que puede incluir comentarios y explicaciones. Se puede ofrecer soporte adicional a los usuarios a través de foros, listas de correo, una dirección de correo electrónico de contacto o un sistema de seguimiento de errores en línea. El software / n ofrece un amplio soporte por una tarifa adicional.

La motivación de un administrador de soporte es un factor importante para un soporte rápido. Los administradores de soporte pueden ser:

  • Un individuo voluntario ( I )
  • Un grupo voluntario ( G )
  • Una entidad profesional pagada para brindar apoyo ( P )

Licencia

Para proyectos comerciales, una licencia de producto es un asunto importante a considerar desde el principio. Algunas bibliotecas se pueden redistribuir libremente en productos comerciales y otras no. Por ejemplo, GPL (GNU General Public License) es una licencia fuerte y limitante, mientras que la licencia de Apache Software solo requiere una mención en los productos redistribuidos.

Las licencias comerciales limitan el número de estaciones de trabajo de desarrollo que programan con la biblioteca, pero la distribución de la biblioteca en sí no está restringida.

Para proyectos no comerciales, la licencia es más una cuestión de filosofía; un producto gratuito es apreciable.

Las licencias pueden ser:

  • Comercial ( C )
  • GPL ( G )
  • Free (F); however, check a free license for limitations

Some library providers provide alternate, less-restrictive licenses on demand.

Source code provided

A closed-sourced, black-box software library can be irritating. Having source code can be more comfortable for the following reasons:

  • When debugging application code execution, stepping into the library code source can help you understand library behavior
  • The source code has useful comments
  • Source code can be quickly tweaked to match special needs
  • Exemplary source code can be inspiring

Age

Libraries have been tested, debugged, and supported since their first public release. As version numbering varies among libraries, I base this criterion on the year of the earliest public release.

Directory listing support

Retrieving remote file information (name, size, date) from the server is important in most applications. The FTP protocol offers the NLST command to retrieve the file names only; the NLST command is explicitly designed to be exploited by programs. The LIST command offers more file information; as RFC959 notes, "Since the information on a file may vary widely from system to system, this information may be hard to use automatically in a program, but may be quite useful to a human user." No other standard method retrieves file information; therefore, client libraries try to exploit the LIST response. But this is not an easy task: since no authoritative recommendation is available for the LIST response format, FTP servers have adopted various formats:

  • Unix style: drwxr-xr-x 1 user01 ftp 512 Jan 29 23:32 prog
  • Alternate Unix style: drwxr-xr-x 1 user01 ftp 512 Jan 29 1997 prog
  • Alternate Unix style: drwxr-xr-x 1 1 1 512 Jan 29 23:32 prog
  • A symbolic link in Unix style: lrwxr-xr-x 1 user01 ftp 512 Jan 29 23:32 prog -> prog2000
  • Weird Unix style (no space between user and group): drwxr-xr-x 1 usernameftp 512 Jan 29 23:32 prog
  • MS-DOS style: 01-29-97 11:32PM prog
  • Macintosh style: drwxr-xr-x folder 0 Jan 29 23:32 prog
  • OS/2 style: 0 DIR 01-29-97 23:32 PROG

Unix style, then MS-DOS style, are the most widespread formats.

Java FTP client libraries try to understand and auto-detect as many formats as possible. In addition, they offer various alternatives for handling unexpected format answers:

  • An additional method returning a raw FTP response as one string (S)
  • An additional method returning a collection of raw strings, one string per line/file (C)
  • A framework supporting pluggable parsers (P)

Most libraries parse LIST responses and structure raw file information into Java objects. For example, with JScape iNet Factory, the following code retrieves and exploits file information received in a directory listing:

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 } 

Section "Solutions for Remaining Problems" further considers directory listings.

Timestamp retrieval

In many cases, we are interested in a remote file's latest modification timestamp. Unfortunately, no RFC introduces a standard FTP command to retrieve this information. Two de facto methods exist:

  1. Retrieve this information from the LIST response by parsing the server answer. Unfortunately, as you learned in the previous section, the LIST response varies among FTP servers, and the timestamp information is sometimes incomplete. In the Unix format, imprecision occurs when the remote file is more than one year old: only the date and year, but not hours or minutes are given.
  2. Use the nonstandard MDTM command, which specifically retrieves a remote file's last modification timestamp. Unfortunately, not all FTP servers implement this command.

An intricate alternative to MDTM command support is to send a raw MDTM command and parse the response. Most libraries provide a method for sending a raw FTP command, something like:

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

Another possible concern is that FTP servers return time information in GMT (Greenwich Mean Time). If the server time zone is known apart from FTP communication, the java.util.TimeZone.getOffset() method can help adjust a date between time zones. See JDK documentation for further information about this method.

Section "Solutions for Remaining Problems" further considers file timestamp retrieval.

Firewalls

Typically, a firewall is placed between a private enterprise network and a public network such as the Internet. Access is managed from the private network to the public network, but access is denied from the public network to the private network.

Socks is a publicly available protocol developed for use as a firewall gateway for the Internet. The JDK supports Socks 4 and Socks 5 proxies, which can be controlled by some of the libraries. As an alternative, the JVM command line can set the Socks proxy parameters: java -DsocksProxyPort=1080 -DsocksProxyHost=socks.foo.com -Djava.net.socks.username=user01 -Djava.net.socks.password=pass1234 ...

Another common alternative to Socks proxy support is to "socksify" the underlying TCP/IP layer on the client machine. A product like Hummingbird can do that job.

The JDK also supports HTTP tunnels. These widespread proxies do not allow FTP uploads. /n software's IP*Works allows you to set HTTP tunnel parameters.

La mayoría de las bibliotecas admiten conexiones tanto activas como pasivas: la conexión pasiva es útil cuando el cliente está detrás de un firewall que inhibe las conexiones entrantes a puertos superiores. RFC1579 analiza esta funcionalidad amigable con el firewall con más detalle. La documentación de algunos productos se refiere a conexiones activas y pasivas como comandos PORTy PASV, respectivamente.

Transferencia paralela

En una aplicación de escritorio, cuando se inicia una transferencia en el hilo principal, todo se congela. Algunas bibliotecas dan servicio automáticamente al bucle de eventos para transferencias paralelas en subprocesos separados para que no tengamos que crear y administrar nuestros propios subprocesos.

Soporte de especificación JavaBean

Algunas bibliotecas implementan la especificación JavaBean. El cumplimiento de JavaBean permite la programación visual, que se incluye en los principales IDE de Java.