【问题标题】:Sidekiq + Carrierwave + S3 (Image upload in background)Sidekiq + Carrierwave + S3(后台上传图片)
【发布时间】:2016-11-11 06:58:55
【问题描述】:

我想在后台上传用户的个人资料图片,因为图片可能很大。我将为此使用 Carrierwave + Fog (Amazon S3) + Sidekiq。

我可以在没有 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

models/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 来解决。但我想尝试了解如何在不使用 gem 的情况下做到这一点。

【问题讨论】:

  • 为什么不能在 Sidekiq 中使用控制器中的相同代码? User.find(user_id).profile_image = image_path。然后在你的控制器ProfilePictureUploadJob.perform_async(@user.id, params[:profile_picture])
  • @MuradYusufov 我认为 Sidekiq 不接受 ActionDispatch::Http::UploadedFile
  • 来自api.rubyonrails.org/classes/ActionDispatch/Http/… :上传的文件是临时文件,其生命周期是一个请求。当对象最终确定时,Ruby 会取消链接文件,因此无需使用单独的维护任务来清理它们。所以我不确定您是否可以在请求完成后访问上传的文件。
  • 我明白了。你能想到任何可行的解决方案吗?
  • 为什么不用carrierwave_backgrounder?

标签: ruby-on-rails sidekiq


【解决方案1】:

解决方案是将临时文件的路径传递给 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

更新:

但是这个解决方案不适用于 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

【讨论】:

    猜你喜欢
    • 2015-04-04
    • 2012-10-30
    • 1970-01-01
    • 2016-04-15
    • 2015-03-15
    • 1970-01-01
    • 2013-01-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多