简体   繁体   中英

Sidekiq + Carrierwave + S3 (Image upload in background)

I want to upload a user's profile picture in the background since the picture can be large. I am going to use Carrierwave + Fog (Amazon S3) + Sidekiq for this.

I can implement it without Sidekiq first:

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

It works perfectly without any hassle. Now, I want to offload this job to a sidekiq worker.

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

Since you can't pass a binary file to Redis, I thought I'd have to pass the path of the temporarily uploaded file. But I can't find a way to actually upload it with Sidekiq.

I think this can be solved by using Carrierwave_Backgrounder gem. But I wanted to try to understand how to do it without using the gem.

The solution is to pass the path to the temporary file to SideKiq's worker, and opening it before uploading it via 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:

But this solution doesn't work on 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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM