Przegląd bibliotek klienta Java FTP

Wyobraźmy sobie sytuację, w której chcemy napisać czystą aplikację Java, która musi pobierać pliki ze zdalnego komputera z serwerem FTP. Chcemy również filtrować pobieranie na podstawie informacji o zdalnym pliku, takich jak nazwa, data lub rozmiar.

Chociaż napisanie programu obsługi protokołu dla FTP od zera jest możliwe i może zabawne, zrobienie tego jest również trudne, długie i potencjalnie ryzykowne. Ponieważ wolelibyśmy nie poświęcać czasu, wysiłku ani pieniędzy na samodzielne pisanie programu obsługi, wolimy zamiast tego ponownie wykorzystać istniejący komponent oprogramowania. W sieci WWW dostępnych jest wiele bibliotek. Dzięki bibliotece klienta FTP pobieranie pliku można zapisać w języku Java tak prosto, jak:

FTPClient ftpClient = nowy FTPClient (); ftpClient.connect ("ftp.foo.com", "user01", "pass1234"); ftpClient.download ("C: \\ Temp \\", "README.txt"); // W końcu inne operacje tutaj ... ftpClient.disconnect ();

Poszukiwanie wysokiej jakości biblioteki klienta FTP Java, która odpowiada naszym potrzebom, nie jest tak proste, jak się wydaje; może to być dość bolesne. Znalezienie biblioteki klienta FTP Java zajmuje trochę czasu. Następnie, po znalezieniu wszystkich istniejących bibliotek, którą wybieramy? Każda biblioteka ma inne potrzeby. Biblioteki mają nierówną jakość, a ich projekty różnią się zasadniczo. Każda z nich oferuje inny zestaw funkcji i do ich opisu używa się innego rodzaju żargonu.

Dlatego ocena i porównanie bibliotek klienta FTP może okazać się trudne i mylące. Ponowne wykorzystanie istniejących komponentów jest procesem godnym pochwały, ale w tym przypadku rozpoczęcie pracy może zniechęcać. A szkoda: po wybraniu dobrej biblioteki FTP reszta to rutyna.

Ten artykuł ma na celu uczynienie tego procesu selekcji krótkim, łatwym i wartościowym. Najpierw wymieniam wszystkie dostępne biblioteki klientów FTP. Następnie definiuję i opisuję listę istotnych kryteriów, którymi biblioteki powinny się w jakiś sposób zająć. Na koniec przedstawiam macierz przeglądową, która daje szybki wgląd w to, jak biblioteki zestawiają się ze sobą. Wszystkie te informacje zapewniają wszystko, czego potrzebujemy, aby podjąć szybką, rzetelną i długotrwałą decyzję.

Obsługa FTP w JDK

Specyfikacją odniesienia dla protokołu FTP jest Request for Comments: 959 (RFC959). Sun Microsystems zapewnia implementację RFC959 w JDK, ale jest ona wewnętrzna, nieudokumentowana i nie ma źródła. Chociaż RFC959 leży w cieniu, w rzeczywistości jest to zaplecze publicznego interfejsu implementującego RFC1738, specyfikację adresu URL, jak pokazano na rysunku 1.

Implementacja RFC1738 jest oferowana jako standard w JDK. Wykonuje rozsądną pracę przy podstawowych operacjach przesyłania FTP. Jest publiczna i udokumentowana, a kod źródłowy jest dostarczany. Aby z niego skorzystać, piszemy:

URL url = nowy adres URL ("ftp: // użytkownik01: [email protected]/README.txt; type = i"); URLConnection urlc = url.openConnection (); InputStream to = urlc.getInputStream (); // Aby pobrać OutputStream os = urlc.getOutputStream (); // Przesłać

Obsługa klienta FTP w JDK jest ściśle zgodna ze standardowymi zaleceniami, ale ma kilka wad:

  • Zasadniczo różni się od bibliotek klienta FTP innych firm; te implementują RFC959 zamiast RFC1738.
  • RFC959 jest zaimplementowany w większości narzędzi klienta FTP na komputery stacjonarne. Wielu programistów Java używa tych narzędzi do łączenia się z serwerami FTP. Z punktu widzenia gustu narzędzia te najprawdopodobniej preferują biblioteki podobne do RFC959.
  • Te URLi URLConnectionzajęcia otwarte strumienie tylko do komunikacji. Słońce oferty biblioteki nie prosto wsparcie dla strukturyzacji surowe odpowiedzi serwera FTP na bardziej użytkowej obiektów jak Java String, File, RemoteFile, lub Calendar. Musimy więc napisać więcej kodu, aby zapisać dane do pliku lub wykorzystać listę katalogów.
  • Jak wyjaśniono w sekcji 3.2.5 dokumentu RFC1738, „Optymalizacja”, adresy URL FTP wymagają, aby połączenie (sterujące) było zamykane po każdej operacji. Jest to marnotrawstwo i nieefektywne przy przesyłaniu wielu małych plików. Ponadto bardzo restrykcyjne serwery FTP mogą uznać taki narzut komunikacyjny za zły atak sieciowy lub nadużycie i odmówić dalszej usługi.
  • Wreszcie brakuje kilku przydatnych funkcji.

Z każdego z tych powodów preferowane jest korzystanie z biblioteki innej firmy. W poniższej sekcji wymieniono dostępne alternatywy innych firm.

Porównanie bibliotek

Poniższa lista przedstawia biblioteki, które porównuję w tym artykule. Wszystkie są zgodne z referencyjną specyfikacją FTP. Poniżej podaję nazwę dostawcy i nazwę biblioteki (kursywą). Zasoby zawierają łącza do witryn internetowych poszczególnych produktów. Aby skorzystać z biblioteki Jumpstart, wspomnę również o głównej klasie klienta FTP.

  1. JScape, iNet Factory :com.jscape.inet.ftp.Ftp
  2. / n oprogramowanie, IP * Działa :ipworks.Ftp
  3. Enterprise Distributed Technologies, Java FTP Client Library :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. Projekt Jakarta, Jakarta Commons / Net :org.apache.commons.net.ftp.FTPClient
  7. JavaShop JNetBeans :jshop.jnet.FTPClient
  8. Słońce, JDK :sun.net.ftp.FtpClient
  9. Florent Cueto, API JavaFTP :com.cqs.ftp.FTP
  10. Bea Petrovicova, jFTP :cz.dhl.ftp.Ftp
  11. Projekt Globus, zestaw Java CoG :org.globus.io.ftp.FTPClient

Uwagi:

  • W chwili pisania tego tekstu IBM ocenia stosowność oferowania pakietu alphaWorks FTP Bean Suite w swojej witrynie internetowej. Na razie pobieranie jest zamknięte dla wszystkich użytkowników.
  • Jakarta Commons / Net to drop-in zamiennik Savarese NetComponents, który nie jest już rozwijany.
  • Wydaje się, że JavaShop JNetBeans został porzucony. W czasie, gdy to piszę, strona była offline przez ponad miesiąc i nigdy nie otrzymałem odpowiedzi na moje prośby o wsparcie.

Kryteria

So far, I have introduced the context and listed the available libraries. Now, I list the relevant criteria against which each library will be evaluated. I enumerate possible values for each criterion, along with the abbreviation (in bold) used in the final comparison matrix.

Product support

The libraries provide support to users through product documentation, compiled Javadocs, sample code, and an example application that can include comments and explanations. Additional support can be offered to users through forums, mailing lists, a contact email address, or an online bug tracking system. /n software offers extensive support for an additional fee.

A support administrator's motivation is an important factor for fast support. Support administrators can be:

  • A voluntary individual (I)
  • A voluntary group (G)
  • A professional entity paid to provide support (P)

License

For commercial projects, a product license is an important matter to consider from the beginning. Some libraries can be freely redistributed in commercial products and others cannot. For instance, GPL (GNU General Public License) is a strong, limiting license, while the Apache Software license only requires a mention in redistributed products.

Commercial licenses limit the number of development workstations programming with the library, but distribution of the library itself is not restricted.

For noncommercial projects, license is more a matter of philosophy; a free product is appreciable.

Licenses can be:

  • Commercial (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.

Większość bibliotek obsługuje zarówno połączenia aktywne, jak i pasywne: połączenie pasywne jest przydatne, gdy klient znajduje się za zaporą sieciową, która blokuje połączenia przychodzące do wyższych portów. RFC1579 bardziej szczegółowo omawia tę przyjazną dla zapory funkcjonalność. Dokumentacje niektórych produktów odnoszą się do połączeń aktywnych i pasywnych odpowiednio jako polecenia PORTi PASV.

Transfer równoległy

W aplikacji komputerowej, gdy transfer rozpoczyna się w głównym pojedynczym wątku, wszystko zawiesza się. Niektóre biblioteki automatycznie obsługują pętlę zdarzeń dla równoległych transferów w oddzielnych wątkach, więc nie musimy tworzyć i zarządzać własnymi wątkami.

Obsługa specyfikacji JavaBean

Niektóre biblioteki implementują specyfikację JavaBean. Zgodność z JavaBean umożliwia programowanie wizualne, które jest obecne w głównych środowiskach Java IDE.