class Net::FTP

此类实现了文件传输协议。如果您使用过命令行 FTP 程序,并且熟悉这些命令,您将能够轻松使用此类。其中包含一些额外的功能,以利用 Ruby 的风格和优势。

示例

require 'net/ftp'

示例 1

ftp = Net::FTP.new('example.com')
ftp.login
files = ftp.chdir('pub/lang/ruby/contrib')
files = ftp.list('n*')
ftp.getbinaryfile('nif.rb-0.91.gz', 'nif.gz', 1024)
ftp.close

示例 2

Net::FTP.open('example.com') do |ftp|
  ftp.login
  files = ftp.chdir('pub/lang/ruby/contrib')
  files = ftp.list('n*')
  ftp.getbinaryfile('nif.rb-0.91.gz', 'nif.gz', 1024)
end

主要方法

以下是用户最可能使用的方法

大型机用户支持

常量

CASE_DEPENDENT_PARSER
CASE_INDEPENDENT_PARSER
DECIMAL_PARSER
FACT_PARSERS
OCTAL_PARSER
TIME_PARSER

属性

binary[R]

true 时,传输以二进制模式执行。默认值:true

debug_mode[RW]

true 时,所有与服务器的流量都会写入 +$stdout+。默认值:false

debug_output[RW]

设置或检索调试的输出流。仅当 debug_mode 设置为 true 时才使用输出流。默认值是 +$stdout+。

last_response[R]

服务器的最后响应。

last_response_code[R]

服务器的最后响应代码。

lastresp[R]

服务器的最后响应代码。

open_timeout[RW]

等待连接打开的秒数。可以使用任何数字,包括小数秒的浮点数。如果 FTP 对象无法在此秒数内打开连接,则会引发 Net::OpenTimeout 异常。默认值为 nil

passive[RW]

true 时,连接处于被动模式。默认值:true

read_timeout[R]

等待读取一个数据块(通过一个 read(2) 调用)的秒数。可以使用任何数字,包括小数秒的浮点数。如果 FTP 对象无法在此秒数内读取数据,则会引发 Timeout::Error 异常。默认值为 60 秒。

resume[RW]

设置或检索 resume 状态,该状态决定是否恢复或重新启动未完成的传输。默认值:false

ssl_handshake_timeout[RW]

等待 TLS 握手的秒数。可以使用任何数字,包括小数秒的浮点数。如果 FTP 对象无法在此秒数内完成 TLS 握手,则会引发 Net::OpenTimeout 异常。默认值为 nil。如果 ssl_handshake_timeoutnil,则改用 open_timeout

use_pasv_ip[RW]

true 时,使用 PASV 响应中的 IP 地址。否则,它使用与控制连接相同的 IP 地址。默认值:false

welcome[R]

服务器的欢迎消息。

公共类方法

default_passive() 点击切换源代码

true 时,默认情况下连接处于被动模式。默认值:true

# File net-ftp-0.3.8/lib/net/ftp.rb, line 165
def self.default_passive
  @@default_passive
end
default_passive=(value) 点击切换源代码

true 时,默认情况下连接处于被动模式。默认值:true

# File net-ftp-0.3.8/lib/net/ftp.rb, line 159
def self.default_passive=(value)
  @@default_passive = value
end
Net::FTP.new(host = nil, options = {}) 点击切换源代码

创建并返回一个新的 FTP 对象。如果给定 host,则建立连接。

options 是一个选项哈希,每个键都是一个符号。

可用的选项有

port

端口号(默认值为 21)

ssl

如果 options[:ssl] 为 true,则将尝试使用 SSL(现在是 TLS)连接到服务器。为此,需要安装 OpenSSL [OSSL] 和 Ruby OpenSSL [RSSL] 扩展。如果 options[:ssl] 是一个哈希,则将其作为参数传递给 OpenSSL::SSL::SSLContext#set_params。

private_data_connection

如果为 true,则数据连接使用 TLS。默认值:当 options[:ssl] 为 true 时为 true

implicit_ftps

如果为 true,则在初始连接上建立 TLS。默认值:false

username

登录的用户名。如果 options[:username] 是字符串“anonymous”,并且 options[:password] 为 nil,则使用“anonymous@”作为密码。

password

登录的密码。

account

ACCT 的帐户信息。

passive

true 时,连接处于被动模式。默认值:true

open_timeout

等待连接打开的秒数。有关详细信息,请参阅 Net::FTP#open_timeout。默认值:nil

read_timeout

等待读取一个数据块的秒数。有关详细信息,请参阅 Net::FTP#read_timeout。默认值:60

ssl_handshake_timeout

等待 TLS 握手的秒数。有关详细信息,请参阅 Net::FTP#ssl_handshake_timeout。默认值:nil

use_pasv_ip

true 时,使用 PASV 响应中的 IP 地址。否则,它使用与控制连接相同的 IP 地址。默认值:false

debug_mode

true 时,所有与服务器的流量都会写入 +$stdout+。默认值:false

调用超类方法
# File net-ftp-0.3.8/lib/net/ftp.rb, line 230
def initialize(host = nil, user_or_options = {}, passwd = nil, acct = nil)
  super()
  begin
    options = user_or_options.to_hash
  rescue NoMethodError
    # for backward compatibility
    options = {}
    options[:username] = user_or_options
    options[:password] = passwd
    options[:account] = acct
  end
  @host = nil
  if options[:ssl]
    unless defined?(OpenSSL::SSL)
      raise "SSL extension not installed"
    end
    ssl_params = options[:ssl] == true ? {} : options[:ssl]
    @ssl_context = SSLContext.new
    @ssl_context.set_params(ssl_params)
    if defined?(VerifyCallbackProc)
      @ssl_context.verify_callback = VerifyCallbackProc
    end

    # jruby-openssl does not support session caching
    unless RUBY_ENGINE == "jruby"
      @ssl_context.session_cache_mode =
        OpenSSL::SSL::SSLContext::SESSION_CACHE_CLIENT |
        OpenSSL::SSL::SSLContext::SESSION_CACHE_NO_INTERNAL_STORE
      @ssl_context.session_new_cb = proc {|sock, sess| @ssl_session = sess }
    end

    @ssl_session = nil
    if options[:private_data_connection].nil?
      @private_data_connection = true
    else
      @private_data_connection = options[:private_data_connection]
    end
    if options[:implicit_ftps].nil?
      @implicit_ftps = false
    else
      @implicit_ftps = options[:implicit_ftps]
    end
  else
    @ssl_context = nil
    if options[:private_data_connection]
      raise ArgumentError,
        "private_data_connection can be set to true only when ssl is enabled"
    end
    @private_data_connection = false
    if options[:implicit_ftps]
      raise ArgumentError,
            "implicit_ftps can be set to true only when ssl is enabled"
    end
    @implicit_ftps = false
  end
  @binary = true
  if options[:passive].nil?
    @passive = @@default_passive
  else
    @passive = options[:passive]
  end
  if options[:debug_mode].nil?
    @debug_mode = false
  else
    @debug_mode = options[:debug_mode]
  end
  @debug_output = $stdout
  @resume = false
  @bare_sock = @sock = NullSocket.new
  @logged_in = false
  @open_timeout = options[:open_timeout]
  @ssl_handshake_timeout = options[:ssl_handshake_timeout]
  @read_timeout = options[:read_timeout] || 60
  @use_pasv_ip = options[:use_pasv_ip] || false
  if host
    connect(host, options[:port] || FTP_PORT)
    if options[:username]
      login(options[:username], options[:password], options[:account])
    end
  end
end
open(host, *args) { |ftp| ... } 点击切换源代码

FTP.new 的同义词,但带有强制性的主机参数。

如果给定了块,则会将 FTP 对象传递给该块,该对象将在块完成或引发异常时关闭。

# File net-ftp-0.3.8/lib/net/ftp.rb, line 175
def FTP.open(host, *args)
  if block_given?
    ftp = new(host, *args)
    begin
      yield ftp
    ensure
      ftp.close
    end
  else
    new(host, *args)
  end
end

公共实例方法

abort() 点击切换源代码

中止上一个命令(ABOR 命令)。

# File net-ftp-0.3.8/lib/net/ftp.rb, line 1283
def abort
  line = "ABOR" + CRLF
  debug_print "put: ABOR"
  @sock.send(line, Socket::MSG_OOB)
  resp = getmultiline
  unless ["426", "226", "225"].include?(resp[0, 3])
    raise FTPProtoError, resp
  end
  return resp
end
acct(account) 点击切换源代码

发送 ACCT 命令。

这是一个不太常见的 FTP 命令,用于在目标主机需要时发送帐户信息。

# File net-ftp-0.3.8/lib/net/ftp.rb, line 925
def acct(account)
  cmd = "ACCT " + account
  voidcmd(cmd)
end
binary=(newmode) 点击切换源代码

用于切换二进制模式传输的 setter。newmodetruefalse

# File net-ftp-0.3.8/lib/net/ftp.rb, line 314
def binary=(newmode)
  if newmode != @binary
    @binary = newmode
    send_type_command if @logged_in
  end
end
chdir(dirname) 点击切换源代码

更改(远程)目录。

# File net-ftp-0.3.8/lib/net/ftp.rb, line 1194
def chdir(dirname)
  if dirname == ".."
    begin
      voidcmd("CDUP")
      return
    rescue FTPPermError => e
      if e.message[0, 3] != "500"
        raise e
      end
    end
  end
  cmd = "CWD #{dirname}"
  voidcmd(cmd)
end
close() 点击切换源代码

关闭连接。除非使用 connect 打开新连接,否则无法进行进一步的操作。

# File net-ftp-0.3.8/lib/net/ftp.rb, line 1397
def close
  if @sock and not @sock.closed?
    begin
      @sock.shutdown(Socket::SHUT_WR) rescue nil
      orig, self.read_timeout = self.read_timeout, 3
      @sock.read rescue nil
    ensure
      @sock.close
      self.read_timeout = orig
    end
  end
end
closed?() 点击切换源代码

当且仅当连接关闭时返回 true

# File net-ftp-0.3.8/lib/net/ftp.rb, line 1413
def closed?
  @sock == nil or @sock.closed?
end
connect(host, port = FTP_PORT) 点击切换源代码

建立与主机的 FTP 连接,可以选择覆盖默认端口。如果设置了环境变量 SOCKS_SERVER,则通过 SOCKS 代理建立连接。如果无法建立连接,则会引发异常(通常为 Errno::ECONNREFUSED)。

# File net-ftp-0.3.8/lib/net/ftp.rb, line 402
def connect(host, port = FTP_PORT)
  debug_print "connect: #{host}:#{port}"
  synchronize do
    @host = host
    @bare_sock = open_socket(host, port)
    if @ssl_context
      begin
        unless @implicit_ftps
          set_socket(BufferedSocket.new(@bare_sock, read_timeout: @read_timeout))
          voidcmd("AUTH TLS")
        end
        set_socket(BufferedSSLSocket.new(start_tls_session(@bare_sock), read_timeout: @read_timeout), @implicit_ftps)
        if @private_data_connection
          voidcmd("PBSZ 0")
          voidcmd("PROT P")
        end
      rescue OpenSSL::SSL::SSLError, OpenTimeout
        @sock.close
        raise
      end
    else
      set_socket(BufferedSocket.new(@bare_sock, read_timeout: @read_timeout))
    end
  end
end
debug_print(msg) 点击切换源代码

将调试消息写入调试输出流

# File net-ftp-0.3.8/lib/net/ftp.rb, line 1488
def debug_print(msg)
  @debug_output << msg + "\n" if @debug_mode && @debug_output
end
delete(filename) 点击切换源代码

删除服务器上的文件。

# File net-ftp-0.3.8/lib/net/ftp.rb, line 1180
def delete(filename)
  resp = sendcmd("DELE #{filename}")
  if resp.start_with?("250")
    return
  elsif resp.start_with?("5")
    raise FTPPermError, resp
  else
    raise FTPReplyError, resp
  end
end
dir(*args)
别名:list
features() 点击切换源代码

发出 FEAT 命令

返回一个支持的可选功能数组

# File net-ftp-0.3.8/lib/net/ftp.rb, line 1363
def features
  resp = sendcmd("FEAT")
  if !resp.start_with?("211")
    raise FTPReplyError, resp
  end

  feats = []
  resp.each_line do |line|
    next if !line.start_with?(' ') # skip status lines

    feats << line.strip
  end

  return feats
end
get(remotefile, localfile = File.basename(remotefile), blocksize = DEFAULT_BLOCKSIZE) { |data| ... } 点击切换源代码

以会话设置的任何模式(文本或二进制)检索 remotefile。请参阅 gettextfilegetbinaryfile

# File net-ftp-0.3.8/lib/net/ftp.rb, line 849
def get(remotefile, localfile = File.basename(remotefile),
        blocksize = DEFAULT_BLOCKSIZE, &block) # :yield: data
  if @binary
    getbinaryfile(remotefile, localfile, blocksize, &block)
  else
    gettextfile(remotefile, localfile, &block)
  end
end
getbinaryfile(remotefile, localfile = File.basename(remotefile), blocksize = DEFAULT_BLOCKSIZE) { |data| ... } 点击切换源代码

以二进制模式检索 remotefile,并将结果存储在 localfile 中。如果 localfile 为 nil,则返回检索到的数据。如果提供了块,则会将检索到的数据以 blocksize 块传递给它。

# File net-ftp-0.3.8/lib/net/ftp.rb, line 788
def getbinaryfile(remotefile, localfile = File.basename(remotefile),
                  blocksize = DEFAULT_BLOCKSIZE, &block) # :yield: data
  f = nil
  result = nil
  if localfile
    if @resume
      rest_offset = File.size?(localfile)
      f = File.open(localfile, "a")
    else
      rest_offset = nil
      f = File.open(localfile, "w")
    end
  elsif !block_given?
    result = String.new
  end
  begin
    f&.binmode
    retrbinary("RETR #{remotefile}", blocksize, rest_offset) do |data|
      f&.write(data)
      block&.(data)
      result&.concat(data)
    end
    return result
  ensure
    f&.close
  end
end
getdir()
别名:pwd
gettextfile(remotefile, localfile = File.basename(remotefile)) { |line| ... } 点击切换源代码

以 ASCII (文本) 模式检索 remotefile,并将结果存储在 localfile 中。如果 localfile 为 nil,则返回检索到的数据。如果提供了块,则会将检索到的数据逐行传递给该块。

# File net-ftp-0.3.8/lib/net/ftp.rb, line 823
def gettextfile(remotefile, localfile = File.basename(remotefile),
                &block) # :yield: line
  f = nil
  result = nil
  if localfile
    f = File.open(localfile, "w")
  elsif !block_given?
    result = String.new
  end
  begin
    retrlines("RETR #{remotefile}") do |line, newline|
      l = newline ? line + "\n" : line
      f&.print(l)
      block&.(line, newline)
      result&.concat(l)
    end
    return result
  ensure
    f&.close
  end
end
help(arg = nil) 点击以切换源代码

发出 HELP 命令。

# File net-ftp-0.3.8/lib/net/ftp.rb, line 1326
def help(arg = nil)
  cmd = "HELP"
  if arg
    cmd = cmd + " " + arg
  end
  sendcmd(cmd)
end
list(*args) { |line| ... } 点击以切换源代码

返回目录中文件信息的数组(输出类似于 “ls -l”)。如果提供了块,则会遍历列表。

# File net-ftp-0.3.8/lib/net/ftp.rb, line 949
def list(*args, &block) # :yield: line
  cmd = "LIST"
  args.each do |arg|
    cmd = "#{cmd} #{arg}"
  end
  lines = []
  retrlines(cmd) do |line|
    lines << line
  end
  if block
    lines.each(&block)
  end
  return lines
end
别名:ls, dir
literal(arguments)
别名:quote
login(user = "anonymous", passwd = nil, acct = nil) 点击以切换源代码

登录到远程主机。会话必须事先已连接。如果 user 是字符串 “anonymous” 且 passwordnil,则使用 “anonymous@” 作为密码。如果 acct 参数不为 nil,则在成功登录后发送 FTP ACCT 命令。如果发生错误,则会引发异常(通常为 Net::FTPPermError)。

# File net-ftp-0.3.8/lib/net/ftp.rb, line 635
def login(user = "anonymous", passwd = nil, acct = nil)
  if user == "anonymous" and passwd == nil
    passwd = "anonymous@"
  end

  resp = ""
  synchronize do
    resp = sendcmd('USER ' + user)
    if resp.start_with?("3")
      raise FTPReplyError, resp if passwd.nil?
      resp = sendcmd('PASS ' + passwd)
    end
    if resp.start_with?("3")
      raise FTPReplyError, resp if acct.nil?
      resp = sendcmd('ACCT ' + acct)
    end
  end
  if !resp.start_with?("2")
    raise FTPReplyError, resp
  end
  @welcome = resp
  send_type_command
  @logged_in = true
end
ls(*args)
别名:list
mdtm(filename) 点击以切换源代码

以 “YYYYMMDDhhmmss” 格式返回(远程)文件的原始最后修改时间 (MDTM 命令)。

如果想要解析的 Time 实例,请使用 mtime

# File net-ftp-0.3.8/lib/net/ftp.rb, line 1316
def mdtm(filename)
  resp = sendcmd("MDTM #{filename}")
  if resp.start_with?("213")
    return get_body(resp)
  end
end
mkdir(dirname) 点击以切换源代码

创建一个远程目录。

# File net-ftp-0.3.8/lib/net/ftp.rb, line 1238
def mkdir(dirname)
  resp = sendcmd("MKD #{dirname}")
  return parse257(resp)
end
mlsd(pathname = nil) { |entry| ... } 点击以切换源代码

返回由 pathname 指定的目录的条目数组。每个条目都有事实信息(例如,大小、最后修改时间等)和路径名。如果提供了块,则会遍历列表。如果省略 pathname,则假定为当前目录。

# File net-ftp-0.3.8/lib/net/ftp.rb, line 1154
def mlsd(pathname = nil, &block) # :yield: entry
  cmd = pathname ? "MLSD #{pathname}" : "MLSD"
  entries = []
  retrlines(cmd) do |line|
    entries << parse_mlsx_entry(line)
  end
  if block
    entries.each(&block)
  end
  return entries
end
mlst(pathname = nil) 点击以切换源代码

返回有关由 pathname 指定的文件或目录的数据(例如,大小、最后修改时间、条目类型等)。如果省略 pathname,则假定为当前目录。

# File net-ftp-0.3.8/lib/net/ftp.rb, line 1132
def mlst(pathname = nil)
  cmd = pathname ? "MLST #{pathname}" : "MLST"
  resp = sendcmd(cmd)
  if !resp.start_with?("250")
    raise FTPReplyError, resp
  end
  line = resp.lines[1]
  unless line
    raise FTPProtoError, resp
  end
  entry = line.sub(/\A(250-| *)/, "")
  return parse_mlsx_entry(entry)
end
mtime(filename, local = false) 点击以切换源代码

返回(远程)文件的最后修改时间。如果 localtrue,则返回本地时间,否则返回 UTC 时间。

# File net-ftp-0.3.8/lib/net/ftp.rb, line 1231
def mtime(filename, local = false)
  return TIME_PARSER.(mdtm(filename), local)
end
nlst(dir = nil) 点击以切换源代码

返回远程目录中文件名的数组。

# File net-ftp-0.3.8/lib/net/ftp.rb, line 933
def nlst(dir = nil)
  cmd = "NLST"
  if dir
    cmd = "#{cmd} #{dir}"
  end
  files = []
  retrlines(cmd) do |line|
    files.push(line)
  end
  return files
end
noop() 点击以切换源代码

发出 NOOP 命令。

除了返回响应之外,不做任何操作。

# File net-ftp-0.3.8/lib/net/ftp.rb, line 1346
def noop
  voidcmd("NOOP")
end
option(name, params = nil) 点击以切换源代码

发出 OPTS 命令

  • name 应该是要设置的选项的名称

  • params 是要与选项一起提供的任何可选参数

示例: option(‘UTF8’, ‘ON’) => ‘OPTS UTF8 ON’

# File net-ftp-0.3.8/lib/net/ftp.rb, line 1386
def option(name, params = nil)
  cmd = "OPTS #{name}"
  cmd += " #{params}" if params

  voidcmd(cmd)
end
put(localfile, remotefile = File.basename(localfile), blocksize = DEFAULT_BLOCKSIZE, &block) 点击以切换源代码

以会话设置的任何模式(文本或二进制)将 localfile 传输到服务器。请参阅 puttextfileputbinaryfile

# File net-ftp-0.3.8/lib/net/ftp.rb, line 910
def put(localfile, remotefile = File.basename(localfile),
        blocksize = DEFAULT_BLOCKSIZE, &block)
  if @binary
    putbinaryfile(localfile, remotefile, blocksize, &block)
  else
    puttextfile(localfile, remotefile, &block)
  end
end
putbinaryfile(localfile, remotefile = File.basename(localfile), blocksize = DEFAULT_BLOCKSIZE) { |data| ... } 点击以切换源代码

以二进制模式将 localfile 传输到服务器,并将结果存储在 remotefile 中。如果提供了块,则会调用它,并以 blocksize 大小的块传入传输的数据。

# File net-ftp-0.3.8/lib/net/ftp.rb, line 863
def putbinaryfile(localfile, remotefile = File.basename(localfile),
                  blocksize = DEFAULT_BLOCKSIZE, &block) # :yield: data
  if @resume
    begin
      rest_offset = size(remotefile)
    rescue Net::FTPPermError
      rest_offset = nil
    end
  else
    rest_offset = nil
  end
  f = File.open(localfile)
  begin
    f.binmode
    if rest_offset
      storbinary("APPE #{remotefile}", f, blocksize, rest_offset, &block)
    else
      storbinary("STOR #{remotefile}", f, blocksize, rest_offset, &block)
    end
  ensure
    f.close
  end
end
puttextfile(localfile, remotefile = File.basename(localfile)) { |line| ... } 点击以切换源代码

以 ASCII (文本) 模式将 localfile 传输到服务器,并将结果存储在 remotefile 中。如果提供了回调或关联的块,则会调用它,并逐行传入传输的数据。

返回响应,如果用户在发出 “quote site filetype=jes” 后以 ASCII 模式与大型机通信,则该响应将包含一个作业号。

# File net-ftp-0.3.8/lib/net/ftp.rb, line 895
def puttextfile(localfile, remotefile = File.basename(localfile), &block) # :yield: line
  f = File.open(localfile)
  response = ''
  begin
    response = storlines("STOR #{remotefile}", f, &block)
  ensure
    f.close
  end
  response
end
pwd() 点击以切换源代码

返回当前远程目录。

# File net-ftp-0.3.8/lib/net/ftp.rb, line 1263
def pwd
  resp = sendcmd("PWD")
  return parse257(resp)
end
别名:getdir
quit() 点击以切换源代码

退出 FTP 会话。

# File net-ftp-0.3.8/lib/net/ftp.rb, line 1337
def quit
  voidcmd("QUIT")
end
quote(arguments) 点击以切换源代码

“quote” 子命令将参数逐字发送到远程 ftp 服务器。“literal” 子命令是 “quote” 的别名。@param arguments 要逐字发送到远程 ftp 服务器的 Array

# File net-ftp-0.3.8/lib/net/ftp.rb, line 1248
def quote(arguments)
  sendcmd(arguments)
end
别名:literal
read_timeout=(sec) 点击以切换源代码

设置 read_timeout 属性。

# File net-ftp-0.3.8/lib/net/ftp.rb, line 142
def read_timeout=(sec)
  @sock.read_timeout = sec
  @read_timeout = sec
end
rename(fromname, toname) 点击以切换源代码

重命名服务器上的文件。

# File net-ftp-0.3.8/lib/net/ftp.rb, line 1169
def rename(fromname, toname)
  resp = sendcmd("RNFR #{fromname}")
  if !resp.start_with?("3")
    raise FTPReplyError, resp
  end
  voidcmd("RNTO #{toname}")
end
retrbinary(cmd, blocksize, rest_offset = nil) { |data| ... } 点击以切换源代码

将连接置于二进制(图像)模式,发出给定的命令,并获取返回的数据,以 blocksize 字符的块将其传递给关联的块。请注意,cmd 是服务器命令(例如 “RETR myfile”)。

# File net-ftp-0.3.8/lib/net/ftp.rb, line 666
def retrbinary(cmd, blocksize, rest_offset = nil) # :yield: data
  synchronize do
    with_binary(true) do
      begin
        conn = transfercmd(cmd, rest_offset)
        while data = conn.read(blocksize)
          yield(data)
        end
        conn.shutdown(Socket::SHUT_WR) rescue nil
        conn.read_timeout = 1
        conn.read rescue nil
      ensure
        conn.close if conn
      end
      voidresp
    end
  end
end
retrlines(cmd) { |line| ... } 点击以切换源代码

将连接置于 ASCII (文本) 模式,发出给定的命令,并将结果数据逐行传递给关联的块。如果没有提供块,则会打印这些行。请注意,cmd 是服务器命令(例如 “RETR myfile”)。

# File net-ftp-0.3.8/lib/net/ftp.rb, line 691
def retrlines(cmd) # :yield: line
  synchronize do
    with_binary(false) do
      begin
        conn = transfercmd(cmd)
        while line = conn.gets
          yield(line.sub(/\r?\n\z/, ""), !line.match(/\n\z/).nil?)
        end
        conn.shutdown(Socket::SHUT_WR) rescue nil
        conn.read_timeout = 1
        conn.read rescue nil
      ensure
        conn.close if conn
      end
      voidresp
    end
  end
end
rmdir(dirname) 点击以切换源代码

删除一个远程目录。

# File net-ftp-0.3.8/lib/net/ftp.rb, line 1256
def rmdir(dirname)
  voidcmd("RMD #{dirname}")
end
sendcmd(cmd) 点击以切换源代码

发送命令并返回响应。

# File net-ftp-0.3.8/lib/net/ftp.rb, line 523
def sendcmd(cmd)
  synchronize do
    putline(cmd)
    return getresp
  end
end
set_socket(sock, get_greeting = true) 点击以切换源代码

设置用于连接到 FTP 服务器的套接字。

如果 get_greeting 为 false,则可能会引发 FTPReplyError。

# File net-ftp-0.3.8/lib/net/ftp.rb, line 432
def set_socket(sock, get_greeting = true)
  synchronize do
    @sock = sock
    if get_greeting
      voidresp
    end
  end
end
site(arg) 点击以切换源代码

发出 SITE 命令。

# File net-ftp-0.3.8/lib/net/ftp.rb, line 1353
def site(arg)
  cmd = "SITE " + arg
  voidcmd(cmd)
end
size(filename) 点击以切换源代码

返回给定(远程)文件的大小。

# File net-ftp-0.3.8/lib/net/ftp.rb, line 1217
def size(filename)
  with_binary(true) do
    resp = sendcmd("SIZE #{filename}")
    if !resp.start_with?("213")
      raise FTPReplyError, resp
    end
    return get_body(resp).to_i
  end
end
status(pathname = nil) 点击以切换源代码

返回状态 (STAT 命令)。

pathname

当使用 pathname 作为参数调用 stat 时,它的行为类似于 list,但速度更快,并且在相同的 tcp 会话中进行。

# File net-ftp-0.3.8/lib/net/ftp.rb, line 1300
def status(pathname = nil)
  line = pathname ? "STAT #{pathname}" : "STAT"
  if /[\r\n]/ =~ line
    raise ArgumentError, "A line must not contain CR or LF"
  end
  debug_print "put: #{line}"
  @sock.send(line + CRLF, Socket::MSG_OOB)
  return getresp
end
storbinary(cmd, file, blocksize, rest_offset = nil) { |data| ... } 点击以切换源代码

将连接置于二进制(图像)模式,发出给定的服务器端命令(例如 “STOR myfile”),并将名为 file 的文件的内容发送到服务器。如果提供了可选的块,它还会以 blocksize 字符的块将其传递给该块。

# File net-ftp-0.3.8/lib/net/ftp.rb, line 716
def storbinary(cmd, file, blocksize, rest_offset = nil) # :yield: data
  if rest_offset
    file.seek(rest_offset, IO::SEEK_SET)
  end
  synchronize do
    with_binary(true) do
      begin
        conn = transfercmd(cmd)
        while buf = file.read(blocksize)
          conn.write(buf)
          yield(buf) if block_given?
        end
        conn.shutdown(Socket::SHUT_WR) rescue nil
        conn.read_timeout = 1
        conn.read rescue nil
      ensure
        conn.close if conn
      end
      voidresp
    end
  end
rescue Errno::EPIPE
  # EPIPE, in this case, means that the data connection was unexpectedly
  # terminated.  Rather than just raising EPIPE to the caller, check the
  # response on the control connection.  If getresp doesn't raise a more
  # appropriate exception, re-raise the original exception.
  getresp
  raise
end
storlines(cmd, file) { |line| ... } 点击以切换源代码

将连接置于 ASCII (文本) 模式,发出给定的服务器端命令(例如 “STOR myfile”),并将名为 file 的文件的内容逐行发送到服务器。如果提供了可选的块,则还会将行传递给该块。

# File net-ftp-0.3.8/lib/net/ftp.rb, line 752
def storlines(cmd, file) # :yield: line
  synchronize do
    with_binary(false) do
      begin
        conn = transfercmd(cmd)
        while buf = file.gets
          if buf[-2, 2] != CRLF
            buf = buf.chomp + CRLF
          end
          conn.write(buf)
          yield(buf) if block_given?
        end
        conn.shutdown(Socket::SHUT_WR) rescue nil
        conn.read_timeout = 1
        conn.read rescue nil
      ensure
        conn.close if conn
      end
      getresp # The response might be important when connected to a mainframe
    end
  end
rescue Errno::EPIPE
  # EPIPE, in this case, means that the data connection was unexpectedly
  # terminated.  Rather than just raising EPIPE to the caller, check the
  # response on the control connection.  If getresp doesn't raise a more
  # appropriate exception, re-raise the original exception.
  getresp
  raise
end
system() 点击以切换源代码

返回系统信息。

# File net-ftp-0.3.8/lib/net/ftp.rb, line 1272
def system
  resp = sendcmd("SYST")
  if !resp.start_with?("215")
    raise FTPReplyError, resp
  end
  return get_body(resp)
end
voidcmd(cmd) 点击以切换源代码

发送命令并期望响应以 “2” 开头。

# File net-ftp-0.3.8/lib/net/ftp.rb, line 533
def voidcmd(cmd)
  synchronize do
    putline(cmd)
    voidresp
  end
end

私有实例方法

parse_mlsx_entry(entry) 点击以切换源代码
# File net-ftp-0.3.8/lib/net/ftp.rb, line 1112
def parse_mlsx_entry(entry)
  facts, pathname = entry.chomp.split(/ /, 2)
  unless pathname
    raise FTPProtoError, entry
  end
  return MLSxEntry.new(
    facts.scan(/(.*?)=(.*?);/).each_with_object({}) {
      |(factname, value), h|
      name = factname.downcase
      h[name] = FACT_PARSERS[name].(value)
    },
    pathname)
end
parse_pasv_ipv4_host(s) 点击以切换源代码
# File net-ftp-0.3.8/lib/net/ftp.rb, line 1438
def parse_pasv_ipv4_host(s)
  return s.tr(",", ".")
end
parse_pasv_ipv6_host(s) 点击以切换源代码
# File net-ftp-0.3.8/lib/net/ftp.rb, line 1443
def parse_pasv_ipv6_host(s)
  return s.split(/,/).map { |i|
    "%02x" % i.to_i
  }.each_slice(2).map(&:join).join(":")
end
parse_pasv_port(s) 点击以切换源代码
# File net-ftp-0.3.8/lib/net/ftp.rb, line 1450
def parse_pasv_port(s)
  return s.split(/,/).map(&:to_i).inject { |x, y|
    (x << 8) + y
  }
end
start_tls_session(sock) 点击以切换源代码
# File net-ftp-0.3.8/lib/net/ftp.rb, line 379
def start_tls_session(sock)
  ssl_sock = SSLSocket.new(sock, @ssl_context)
  ssl_sock.sync_close = true
  ssl_sock.hostname = @host if ssl_sock.respond_to? :hostname=
  if @ssl_session &&
      Process.clock_gettime(Process::CLOCK_REALTIME) < @ssl_session.time.to_f + @ssl_session.timeout
    # ProFTPD returns 425 for data connections if session is not reused.
    ssl_sock.session = @ssl_session
  end
  ssl_socket_connect(ssl_sock, @ssl_handshake_timeout || @open_timeout)
  if @ssl_context.verify_mode != VERIFY_NONE
    ssl_sock.post_connection_check(@host)
  end
  return ssl_sock
end