Die Programmiersprache Ruby

Blog| Forum| Wiki  

FTP Download einer Datei

Sich eine Datei via ftp zu holen, ist mit Ruby einfach:

1
2
3
4
5
6
7
8
9
10
11
 require 'net/ftp'

FTP_SERVER = "ftp.ruby-lang.org"
FILE       = "/pub/ruby/1.8/changes.1.8.0"
USER       = "anonymous"
PASS       = "guest@home"

Net::FTP.open( FTP_SERVER ) do |ftp|
 ftp.login( USER, PASS )
 ftp.getbinaryfile( FILE, File.basename( FILE ) ) 
end


Hier wird die Datei changes.1.8.0 vom Server geholt und ins aktuelle Verzeichnis abgelegt.

In Ruby 1.6.x war open ohne Blockaufruf implementiert. Eine Version, die sowohl unter Version 1.6 wie 1.8 funktioniert, ist diese:

1
2
3
4
5
6
7
8
9
10
11
 require 'net/ftp'

FTP_SERVER = "ftp.ruby-lang.org"
FILE       = "/pub/ruby/1.8/changes.1.8.0"
USER       = "anonymous"
PASS       = "guest@home"

ftp = Net::FTP.open( FTP_SERVER )
  ftp.login( USER, PASS )
  ftp.getbinaryfile( FILE, File.basename( FILE ) ) 
ftp.close


Was manchmal störend sein kann, sind die langen Timeout Zeiten. Bis die ftp-Bibliothek aufgibt, können schonmal 10 Minuten vergehen. Besser ist es dann, eigene Timeouts zu setzen, sowohl für's Login wie auch für die Übertragung. Ruby hat hierfür die timeout-Bibliothek.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
 require 'net/ftp'
require 'timeout'


FTP_SERVER = "ftp.ruby-lang.org"
FILE       = "/pub/ruby/1.8/changes.1.8.0"
USER       = "anonymous"
PASS       = "guest@home"

CON_TIMEOUT      = 30
TRANSFER_TIMEOUT = 600

ftp = nil
begin
  timeout( CON_TIMEOUT ) do
    ftp = Net::FTP.new( FTP_SERVER )
    ftp.login( USER, PASS )
  end

  timeout( TRANSFER_TIMEOUT ) do
    ftp.getbinaryfile( FILE, File.basename( FILE ) )
  end

rescue
  STDERR.puts "Error ftp-transfer server: #{FTP_SERVER}"
  raise
ensure
  ftp.close if ftp
  GC.start
  sleep 5
end


Im ensure Pfad wird auch im Fehlerfall der Socket geschlossen. Bei Tests in Ruby 1.6.x habe ich herausgefunden, dass im Fehlerfall mitunter Sockets nicht korrekt geschlossen wurden. Erst wenn ich den Garbage Collector mit GC.start aufgeräumt habe, war das Schließen erfolgreich. Danach muss noch eine kurze Zeitspanne gewartet werden, damit die Sockets auch im Fehlerfall sauber abgebaut werden. 5 Sekunden ist dabei ein Daumenwert, den man sicherlich noch besser ausloten kann. WinfriedMueller


Unter [1] gibt es einen einfachen FTP-Browser mit GUI als RubyGem.