Module: Paperclip::Storage::Ftp

Defined in:
lib/paperclipftp.rb

Defined Under Namespace

Classes: FtpTimeout

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.extended(base) ⇒ Object



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# File 'lib/paperclipftp.rb', line 6

def self.extended base
  require 'net/ftp'
  base.instance_eval do
    @ftp_credentials = parse_credentials(@options[:ftp_credentials])
    @passive_mode = !!@options[:ftp_passive_mode]
    @debug_mode = !!@options[:ftp_debug_mode]
    @verify_size = !!@options[:ftp_verify_size_on_upload]
    @timeout = @options[:ftp_timeout] || 3600
  end
  # it is better to share and keep ftp connection because otherwise some methods (like
  # exists?, to_file etc) will open new connection each and every time without closing it - bad
  unless base.class.respond_to?(:ftp_conn)
    class << base.class; attr_accessor :ftp_conn; end
  end
end

Instance Method Details

#exists?(style = default_style) ⇒ Boolean

Returns:

  • (Boolean)


22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/paperclipftp.rb', line 22

def exists?(style = default_style)
  begin
    Timeout::timeout(@timeout, FtpTimeout) do
      file_size(ftp_path(style)) > 0
    end
  rescue Timeout::Error => e
    # either a true timeout or a spurious one, solution is simple, close connection and
    # re-raise exception, it is up to higher layers to retry on failure
    debug "Timed out in exists?"
    close_ftp_connection
    raise e
  end
end

#flush_deletesObject



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/paperclipftp.rb', line 83

def flush_deletes
  @queued_for_delete.each do |path|
    Timeout::timeout(@timeout, FtpTimeout) do
      begin
        log("deleting #{path}")
        ftp.delete('/' + path)
      rescue Net::FTPPermError, Net::FTPReplyError
      end
    end
  end
  @queued_for_delete = []
rescue Net::FTPReplyError => e
  raise e
rescue Net::FTPPermError => e
  raise e
ensure
  close_ftp_connection
end

#flush_writesObject



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/paperclipftp.rb', line 48

def flush_writes
  @queued_for_write.each do |style, file|
    Timeout::timeout(@timeout, FtpTimeout) do
      file.close
      remote_path = ftp_path(style)
      log("uploading #{remote_path}")
      first_try = true
      begin
        ftp.putbinaryfile(file.path, remote_path)
      rescue Net::FTPPermError => e
        if first_try
          first_try = false
          create_parent_folder_for(remote_path)
          retry
        else
          raise e
        end
      end
      if @verify_size
        # avoiding those weird occasional 0 file sizes by not using instance method file.size
        local_file_size = File.size(file.path)
        remote_file_size = file_size(remote_path)
        raise Net::FTPError.new("Uploaded #{remote_file_size} bytes instead of #{local_file_size} bytes") unless remote_file_size == local_file_size
      end
    end
  end
  @queued_for_write = {}
rescue Net::FTPReplyError => e
  raise e
rescue Net::FTPPermError => e
  raise e
ensure
  close_ftp_connection
end

#to_file(style = default_style) ⇒ Object Also known as: to_io



36
37
38
39
40
41
42
43
44
# File 'lib/paperclipftp.rb', line 36

def to_file style = default_style
  return @queued_for_write[style] if @queued_for_write[style]
  Timeout::timeout(@timeout, FtpTimeout) do
    file = Tempfile.new(ftp_path(style))
    ftp.getbinaryfile(ftp_path(style), file.path)
    file.rewind
    return file
  end
end