remomueller/aqueduct-ftp

View on GitHub
lib/aqueduct/repositories/ftp.rb

Summary

Maintainability
A
3 hrs
Test Coverage
require 'aqueduct'
require 'net/ftp'

# The default FTP Wrapper will download the file(s) from the remote ftp server and place them in a local
# cache in <Rails.root>/tmp/symbolic/source_<id>/<remote_path>/<file_name>.  This cache essentially makes
# the file service act as if it's a local mounted repository. (And should only be used to get up and
# running quickly.)

# NOTE!
# A Better FTP wrapper would generate a dynamic login and password on the FTP server with a link to that
# server with the appropriate files readily available in a folder so the user can download directly from
# the FTP without having to have the files first downloaded to the server hosting the Rails Application.
# A better FTP wrapper could be implemented as a new wrapper.

module Aqueduct
  module Repositories
    class Ftp
      include Aqueduct::Repository

      def count_files(file_locators, file_type)
        error = ''
        file_paths = []
        url_paths = []
        begin
          ftp = Net::FTP.new #(@source.file_server_host, @source.file_server_login, @source.file_server_password)
          ftp.connect(@source.file_server_host, 21)
          ftp.login(@source.file_server_login, @source.file_server_password)

          ftp.chdir(@source.file_server_path)

          file_locators.each do |file_locator|
            file_locator = file_locator.to_s.gsub(/[\/*]/, '') # Don't allow wild cards or subfolders
            file_type = file_type.to_s.gsub(/[\/*]/, '')       # Don't allow wild cards or subfolders
            file_name = file_locator + file_type
            file_path = File.join(Rails.root, 'tmp', 'symbolic', "source_#{@source.id}", @source.file_server_path)

            if File.exists?(File.join(file_path, file_name))
              # Do nothing
              # Rails.logger.debug "File already exists"
            else
              begin
                # Rails.logger.debug "Retrieving #{file_name} from FTP"
                FileUtils.mkpath(file_path)
                ftp.getbinaryfile(file_name, File.join(file_path, file_name))
              rescue
                # Rails.logger.debug "           #{file_name} not found!"
                File.delete(File.join(file_path, file_name)) if File.exists?(File.join(file_path, file_name))
                file_name = nil
              end
            end

            file_paths << File.join(file_path, file_name) unless file_name.blank?
            url_paths << SITE_URL + "/sources/#{@source.id}/download_file?file_locator=#{file_locator}&file_type=#{file_type}&fn=#{file_name.split('/').last}" unless file_name.blank?

          end
        rescue => e
          error = e.to_s
        ensure
          begin
            ftp.close
          rescue => e
            # We don't care.
          end
        end
        { result: url_paths.size, error: error, file_paths: file_paths, urls: url_paths }
      end

      def get_file(file_locator, file_type)
        result_hash = count_files([file_locator], file_type)
        { file_path: result_hash[:file_paths].first.to_s, error: result_hash[:error] }
      end

      def has_repository?
        { result: true, error: '' }
      end

      def file_server_available?
        result = false
        error = ''
        begin
          ftp = Net::FTP.new
          ftp.connect(@source.file_server_host, 21)
          ftp.login(@source.file_server_login, @source.file_server_password)
          result = true
        rescue => e
          error = e.to_s
        ensure
          begin
            ftp.close
          rescue => e
            # We don't care.
          end
        end
        { result: result, error: error }
      end
    end
  end
end