2011-08-08 33 views
5

我刚开始使用resque在后台对一些非常大的文件进行一些处理,并且我无法弄清楚如何将文件传递给resque worker。我使用rails来处理文件上传,并且rails为从表单上传的每个文件创建一个ActionDispatch::Http::UploadedFile对象。发送上传的文件到resque worker进行处理

如何将此文件发送给resque worker?我尝试发送临时文件和原始文件名的路径名的自定义散列,但我无法重新打开resque工作中的临时文件(只是一个正常的Errno::ENOENT - No such file or directory),因为rails似乎在请求结束后删除该临时文件。

回答

5

Http::UploadedFile一旦请求结束,将无法访问。您需要将文件写入某处(或使用s3作为临时存储)。将resque复制到您写入的文件的路径。

+0

似乎是唯一的方法。我之前只是不想处理文件的移动和删除。谢谢。 –

5

我刚刚花了两天的时间试图做到这一点,并最终找到了答案。您需要对文件进行Base64编码,以便将其序列化为json。然后,你需要它的工人进行解码,并创建一个新的

ActionDispatch::Http::UploadedFile

下面是如何编码,并传递给resque:

// You only need to encode the actual file, everything else in the 
// ActionDispatch::Http::UploadedFile object is just string or a hash of strings 

file = params[:file] // Your ActionDispatch::Http::UploadedFile object 
file.tempfile.binmode 
file.tempfile = Base64.encode64(file.tempfile.read) 

Resque.enqueue(QueueWorker, params) 

,这里是如何解码和内转换回对象你的工人

class QueueWorker 
    @queue = :main_queue 

    def self.perform(params) 
     file = params['file'] 
     tempfile = Tempfile.new('file') 
     tempfile.binmode 
     tempfile.write(Base64.decode64(file['tempfile'])) 

     // Now that the file is decoded you need to build a new 
     // ActionDispatch::Http::UploadedFile with the decoded tempfile and the other 
     // attritubes you passed in. 

     file = ActionDispatch::Http::UploadedFile.new(tempfile: tempfile, filename: file['original_filename'], type: file['content_type'], head: file['headers']) 

     // This object is now the same as the one in your controller in params[:file] 
    end 
end 
+3

我不会推荐这样做,除非您确定您的文件永远不会超过几百KB。将文件写入磁盘/ s3/etc并将该路径传递给Resque作业是处理此问题的正确方法。 – pnomolos

+0

与@pnomolos绝对同意这不适合大文件,但如果您处理的是小文件(例如5-10KB CSV),那么这是一个聪明的黑客,不值得把它们上传到S3然后重新编译的麻烦当你需要它们时下载它们。 – ACIDSTEALTH