我有一个应用程序,用户将直接上传文件到S3。这是行得通的。现在,我需要一个后台工作人员(现在delayed_job)来检索文件并将其保存在'tmp/files'中进行处理。我的Rails应用程序如何从S3下载文件?
这怎么办?
编辑:该应用程序目前正在EC2中运行。
我有一个应用程序,用户将直接上传文件到S3。这是行得通的。现在,我需要一个后台工作人员(现在delayed_job)来检索文件并将其保存在'tmp/files'中进行处理。我的Rails应用程序如何从S3下载文件?
这怎么办?
编辑:该应用程序目前正在EC2中运行。
后台工作人员将独立于您的网络应用运行。
尝试Resque了解常用的Rails后台工作人员解决方案。这个想法是,你独立于你的网络应用程序开始Resque,并且独立于应用程序完成它的工作。
是否有此工作人员向S3发送基本的HTTP请求。这是一个API reference card让你开始。这个想法是,您使用某种Ruby REST客户端发送这些请求,并解析您从S3获得的响应。 Rest-client是你可以用来做这件事的宝石。
或者,您也可以让工作人员使用S3 gem,这可能会更容易一些。
通过这种方法,你有你的工人运行脚本,它有点像
picture = S3Object.find 'headshot.jpg', 'photos'
使用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
触发
你在使用Heroku吗? EC2? – Stpn 2013-02-22 22:01:47
EC2。编辑的问题。谢谢。 – n8gard 2013-02-22 22:05:46
答案有帮助吗? – Stpn 2013-02-23 19:47:38