Being an FTP Client

Being an FTP Client


You want to automatically connect to an FTP server, and upload or download files.


Use the Net::FTP class. It provides a filesystem-like interface to an FTP server. In this example, I log anonymously into a popular FTP site, browse one of its directories, and download two of its files:

	require 'net/ftp'
	ftp ='') do |ftp|
	  ftp.list('*Linux*') { |file| puts file }

	  puts 'Saving a text file to disk while processing it.'
	  ftp.gettextfile('How-do-I-get-Linux') { |line| puts "! #{line}" }
	  puts "Saved #{File.size 'How-do-I-get-Linux'} bytes."

	  puts 'Saving a binary file to disk.'
	 puts "Saved #{File.size 'INDEX.whole.gz'} bytes."
	# -rw-r--r--   1 (?)      users    16979001 Jan 1 11:31 00-find.Linux.gz
	# -rw-rw-r--   1 (?)      admin          73 Mar 9  2001 How-do-I-get-Linux

	# Saving a text file to disk while processing it.
	# !
	# !   Browse to
	# !
	# Saved 73 bytes.

	# Saving a binary file to disk.
	# Saved 213507 bytes.


Once the preferred way of storing and serving files through the Internet, FTP is being largely superceded by SCP for copying files, the web for distributing files, and Bit-Torrent for distributing very large files. There are still many anonymous FTP servers, though, and many web hosting companies still expect you to upload your web pages through FTP.

The login method logs in to the server. Calling it without arguments logs you in anonymously, which traditionally limits you to download privileges. Calling it with a username and password logs you in to the server:

	ftp.login('leonardr', 'mypass')

The methods chdir and list let you navigate the FTP server's directory structure. They work more or less like the Unix cd and ls commands (in fact, list is aliased to ls and dir).

There are also two "get" methods and two "put" methods. The "get" methods are getbinaryfile and gettextfile. They retrieve the named file from the FTP server and write it to disk. The gettextfile method converts between platform-specific newline formats as it downloads. This way you can download a text file from a Unix server to your Windows machine, and have the Unix newlines automatically converted into Windows newlines. On the other hand, if you use gettextfile on a binary file, you'll probably corrupt the file as you download it.

You can specify a local name for the file and a block to process the data as it comes in. A block passed into gettextfile will be called for each line of a downloaded file; a block passed into getbinaryfile will be passed for each downloaded chunk.

A file you download with one of the "get" methods will be written to disk even if you pass in a block to process it. If you want to process a file without writing it to disk, just define some methods like these:

	  def processtextfile(remotefile)
	    retrlines('RETR ' + remotefile) { |line| yield line }

	  def processbinaryfile(remotefile, blocksize=DEFAULT_BLOCKSIZE)
	    retrbinary('RETR ' + remotefile, blocksize) { |data| yield data }

The two "put" methods are (you guessed it) puttextfile and putbinaryfile. They are the exact opposites of their get counterparts: they take the path to a local file, and write it to a file on the FTP server. They, too, can take a code block that processes each line or chunk of the file as it's read. This example automatically uploads the index.html file to my ISP's hosted web space.

	require 'net/ 
ftp''') do |ftp|
	  ftp.login('leonardr', 'mypass')

In general, you can't use the "put" methods if you're logged in as an anonymous user. Some FTP servers do have special incoming/ directories to which anonymous users can upload their submissions.

See Also

  • ri Net::FTP

 Python   SQL   Java   php   Perl 
 game development   web development   internet   *nix   graphics   hardware 
 telecommunications   C++ 
 Flash   Active Directory   Windows