简体   繁体   English

Sidekiq + Carrierwave + S3(背景图片上传)

[英]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. 我将为此使用Carrierwave + Fog(Amazon S3)+ Sidekiq。

I can implement it without Sidekiq first: 我可以先不用Sidekiq来实现它:

users_controller.rb 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 型号/user.rb

mount_uploader :profile_picture, ProfilePictureUploader

It works perfectly without any hassle. 它完美地工作,没有任何麻烦。 Now, I want to offload this job to a sidekiq worker. 现在,我想把这项工作转移给sidekiq工人。

users_controller.rb 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 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. 由于您无法将二进制文件传递给Redis,因此我认为必须传递临时上传文件的路径。 But I can't find a way to actually upload it with Sidekiq. 但是我找不到用Sidekiq实际上传它的方法。

I think this can be solved by using Carrierwave_Backgrounder gem. 我认为可以通过使用Carrierwave_Backgrounder gem来解决。 But I wanted to try to understand how to do it without using the gem. 但是我想尝试了解如何在不使用gem的情况下做到这一点。

The solution is to pass the path to the temporary file to SideKiq's worker, and opening it before uploading it via Carrierwave. 解决方案是将临时文件的路径传递给SideKiq的工作程序,并在通过Carrierwave上传之前打开它。

users_controller.rb 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 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: 但是此解决方案不适用于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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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