2013-02-22 85 views
0

我有一個應用程序,用戶將直接上傳文件到S3。這是行得通的。現在,我需要一個後臺工作人員(現在delayed_job)來檢索文件並將其保存在'tmp/files'中進行處理。我的Rails應用程序如何從S3下載文件?

這怎麼辦?

編輯:該應用程序目前正在EC2中運行。

+0

你在使用Heroku嗎? EC2? – Stpn 2013-02-22 22:01:47

+0

EC2。編輯的問題。謝謝。 – n8gard 2013-02-22 22:05:46

+0

答案有幫助嗎? – Stpn 2013-02-23 19:47:38

回答

0

後臺工作人員將獨立於您的網絡應用運行。

嘗試Resque瞭解常用的Rails後臺工作人員解決方案。這個想法是,你獨立於你的網絡應用程序開始Resque,並且獨立於應用程序完成它的工作。

是否有此工作人員向S3發送基本的HTTP請求。這是一個API reference card讓你開始。這個想法是,您使用某種Ruby REST客戶端發送這些請求,並解析您從S3獲得的響應。 Rest-client是你可以用來做這件事的寶石。

或者,您也可以讓工作人員使用S3 gem,這可能會更容易一些。

通過這種方法,你有你的工人運行腳本,它有點像

picture = S3Object.find 'headshot.jpg', 'photos'

+0

這不回答我的問題。我如何讓工作人員(無論哪種類型)連接到S3並下載文件? – n8gard 2013-02-22 22:00:12

+0

更新了我的答案。如果您需要更多細節,請告訴我。這個問題有點含糊。 – varatis 2013-02-22 22:05:22

0

使用Resque。

添加

gem 'resque' 
gem 'resque-status' 

隨着Resque你需要的Redis(存儲有關人員的信息),要麼使用Redis的到去或您的EC2的機器上本地安裝Redis的。

安裝打完Resque編輯配置/初始化/ resque.rb

rails_root = ENV['RAILS_ROOT'] || File.dirname(__FILE__) + '/../..' 
rails_env = ENV['RAILS_ENV'] || 'production' 
resque_config = YAML.load_file(rails_root + '/config/resque.yml') 
Resque.redis = resque_config[rails_env] 

    # This is if you are using Redis to go: 
    # ENV["REDISTOGO_URL"] ||= "redis://REDISTOGOSTUFFGOESHERE" 
    # uri = URI.parse(ENV["REDISTOGO_URL"]) 
    # Resque.redis = Redis.new(:host => uri.host, :port => uri.port, :password => uri.password, :thread_safe => true) 

Resque::Plugins::Status::Hash.expire_in = (24 * 60 * 60) # 24hrs in seconds 

Dir["#{Rails.root}/app/workers/*.rb"].each { |file| require file } 

這裏我們使用本地Redis的,所以resque.yml看起來是這樣的:

development: localhost:6379 
test: localhost:6379 
fi: localhost:6379 
production: localhost:6379 

您將需要的東西像上帝一樣開始/管理工作人員

因此安裝它然後將「resque-production.god」添加到您的應用的配置/文件夾 您將能夠啓動您的工人通過這樣的:神-c配置/ resque-production.god 配置/ resque-production.god文件預訂購有類似:

rails_env = ENV['RAILS_ENV'] || "production" 
rails_root = ENV['RAILS_ROOT'] || File.dirname(__FILE__) + '/..' 
num_workers = 1 

num_workers.times do |num| 
    God.watch do |w| 
    w.dir  = "#{rails_root}" 
    w.name  = "resque-#{num}" 
    w.group = 'resque' 
    w.interval = 30.seconds 
    w.env  = {"QUEUE"=>"*", "RAILS_ENV"=>"production"} 
    w.start = "rake -f #{rails_root}/Rakefile environment resque:work --trace" 
    w.log  = "#{rails_root}/log/resque.log" 
    w.err_log = "#{rails_root}/log/resque_error.log" 


    # restart if memory gets too high 
    w.transition(:up, :restart) do |on| 
     on.condition(:memory_usage) do |c| 
     c.above = 350.megabytes 
     c.times = 2 
     end 
    end 

    # determine the state on startup 
    w.transition(:init, { true => :up, false => :start }) do |on| 
     on.condition(:process_running) do |c| 
     c.running = true 
     end 
    end 

    # determine when process has finished starting 
    w.transition([:start, :restart], :up) do |on| 
     on.condition(:process_running) do |c| 
     c.running = true 
     c.interval = 5.seconds 
     end 

     # failsafe 
     on.condition(:tries) do |c| 
     c.times = 5 
     c.transition = :start 
     c.interval = 5.seconds 
     end 
    end 

    # start if process is not running 
    w.transition(:up, :start) do |on| 
     on.condition(:process_running) do |c| 
     c.running = false 
     end 
    end 
    end 
end 

最後工人。他們去到應用程序/工人/文件夾(在這裏是應用程序/工人/ processor.rb)

class Processor 
    include Resque::Plugins::Status 
    @queue = :collect_queue 

    def perform 
    article_id = options["article_id"] 
    article = Article.find(article_id) 
    article.download_remote_file(article.file_url) 
    end 
end 

它是由Article模型回調(應用程序/模型/ article.rb)

class Article < ActiveRecord::Base 

    after_create :process 

    def download_remote_file(url) 
    # OpenURI extends Kernel.open to handle URLs as files 
    io = open(url) 

    # overrides Paperclip::Upfile#original_filename; 
    # we are creating a singleton method on specific object ('io') 
    def io.original_filename 
     base_uri.path.split('/').last 
    end 

    io.original_filename.blank? ? nil : io 
    end  

def process 
    Processor.create(:article_id => self.id) 
    end 

end 
觸發
相關問題