2016-11-11 9 views
0

Ich möchte das Profilbild eines Benutzers im Hintergrund hochladen, da das Bild groß sein kann. Ich werde Carrierwave + Fog (Amazon S3) + Sidekiq dafür verwenden.Sidekiq + Carrierwave + S3 (Bild hochladen im Hintergrund)

ich es ohne Sidekiq erste implementieren können:

users_controller.rb

def update 
    @user = User.find(params[:id]) 
    if params[:profile_picture] 
    // params[:profile_picture] has ActionDispatch::Http::UploadedFile type 
    @user.profile_image = params[:profile_picture] 
    end 

    ... 
end 

models/user.rb

mount_uploader :profile_picture, ProfilePictureUploader 

Es funktioniert perfekt ohne jede Hektik. Jetzt möchte ich diesen Job an einen Sidekiq-Mitarbeiter abladen.

users_controller.rb

def update 
    @user = User.find(params[:id]) 
    if params[:profile_picture] 
    // Below path is in this kind of form: 
    // /var/folders/ps/l8lvygws0w93trqz7yj1t5sr0000gn/T/RackMultipart20161110-46798-w9bgb9.jpg 
    @user.profile_image = params[:profile_picture].path 
    end 

    ... 
end 

profile_picture_upload_job.rb

class ProfilePictureUploadJob 
    include Sidekiq::Worker 

    def perform(user_id, image_path) 
    user = User.find(user_id) 
    // HELP: I don't know what to do here! 
    user.remote_profile_picture_url = image_path 
    // user.profile_picture = image_path 
    user.save! 
    end 
end 

Da Sie nicht eine Binärdatei zu Redis passieren kann, dachte ich, ich muss den Weg passieren würde der temporär hochgeladenen Datei. Aber ich kann keine Möglichkeit finden, es mit Sidekiq zu laden.

Ich denke, das kann mit Carrierwave_Backgrounder gem gelöst werden. Aber ich wollte versuchen zu verstehen, wie es geht, ohne den Edelstein zu benutzen.

+0

Warum können Sie nicht einfach den gleichen Code von Ihrem Controller in Sidekiq verwenden? 'User.find (user_id) .profile_image = image_path'. Dann in Ihrem Controller 'ProfilePictureUploadJob.perform_async (@ user.id, params [: profile_picture])' –

+0

@MuradYusufov Ich denke, Sidekiq akzeptiert 'ActionDispatch :: Http :: UploadedFile' –

+0

Von http: //api.rubyonrails. org/classes/ActionDispatch/Http/UploadedFile.html: Hochgeladene Dateien sind temporäre Dateien, deren Lebensdauer eine Anfrage ist. Wenn das Objekt finalisiert ist, hebt Ruby die Datei auf, so dass es nicht nötig ist, sie mit einer separaten Wartungsaufgabe zu säubern. So bin ich nicht sicher, ob Sie auf die hochgeladene Datei zugreifen können, nachdem die Anfrage abgeschlossen ist. –

Antwort

0

Die Lösung besteht darin, den Weg zu der temporären Datei an den Arbeiter von SideKiq zu übergeben und sie vor dem Hochladen über Carrierwave zu öffnen.

users_controller.rb

def update 
    @user = User.find(params[:id]) 
    if params[:profile_picture] 
    // Below path is in this kind of form: 
    // /var/folders/ps/l8lvygws0w93trqz7yj1t5sr0000gn/T/RackMultipart20161110-46798-w9bgb9.jpg 
    @user.profile_image = params[:profile_picture].path 
    end 

    ... 
end 

profile_picture_upload_job.rb

class ProfilePictureUploadJob 
    include Sidekiq::Worker 

    def perform(user_id, image_path) 
    user = User.find(user_id) 
    user.profile_picture = File.open(image_path) 
    user.save! 
    end 
end 

UPDATE:

Aber diese Lösung funktioniert nicht auf Heroku:

2016-11-11T11:34:06.839408+00:00 app[worker.1]: 4 TID-osgdwad5o WARN: Errno::ENOENT: No such file or directory @ rb_sysopen - /tmp/RackMultipart20161111-4-1poz958.jpg 
Verwandte Themen