2016-11-11 3 views
0

Я хочу загрузить изображение профиля пользователя в фоновом режиме, так как изображение может быть большим. Я собираюсь использовать Carrierwave + Fog (Amazon S3) + Sidekiq для этого.Sidekiq + Carrierwave + S3 (Загрузка изображения в фоновом режиме)

можно реализовать без Sidekiq первых:

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 

модели/user.rb

mount_uploader :profile_picture, ProfilePictureUploader 

Он отлично работает без каких-либо хлопот. Теперь, я хочу разгрузить эту работу работнику sidekiq.

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 

Поскольку вы не можете передать двоичный файл в Redis, я думал, что я должен пройти путь временно загруженного файла. Но я не могу найти способ загрузить его с Sidekiq.

Я думаю, что это можно решить, используя Carrierwave_Backgrounder gem. Но я хотел попытаться понять, как это сделать, не используя драгоценный камень.

+0

Почему вы не можете использовать один и тот же код у своего контроллера в Sidekiq? 'User.find (user_id) .profile_image = image_path'. Затем в вашем контроллере 'ProfilePictureUploadJob.perform_async (@ user.id, params [: profile_picture])' –

+0

@MuradYusufov Я думаю, что Sidekiq не принимает 'ActionDispatch :: Http :: UploadedFile' –

+0

С http: //api.rubyonrails. org/classes/ActionDispatch/Http/UploadedFile.html: Загруженные файлы - это временные файлы, срок службы которых - один запрос. Когда объект завершен, Ruby отклеивает файл, поэтому нет необходимости чистить их с помощью отдельной задачи обслуживания. Так что я не уверен, что вы можете получить доступ к загруженному файлу после завершения запроса. –

ответ

0

Решение состоит в том, чтобы передать путь во временный файл работнику SideKiq и открыть его перед загрузкой через Carrierwave.

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:

Но это решение не работает на 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 
Смежные вопросы