2011-08-08 58 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