Carrierwave backgrounder и Heroku - проблема с временным интервалом

Я загружаю изображения в свою модель Picture. Я использую Carrierwave, Carrierwave-Backgrounder, Carrierwave-FTP для SFTP и DelayedJob.

Цель состоит в том, чтобы изображения обрабатывались и сохранялись через SFTP в фоновом режиме. Мой подход отлично работает в моей среде разработки, но не работает на Heroku.

Я понимаю, что это связано с тем, что каталог tmp Heroku стирается после создания действия, но я ищу способ обойти это.

Можно ли использовать S3/Fog для хранения файлов tmp? Затем получите доступ к ним оттуда с помощью Carrierwavebackgrounder. Или есть лучший подход?

Загрузчик:

# encoding: utf-8

class ImageUploader < CarrierWave::Uploader::Base

  def cache_dir
    "#{Rails.root}/tmp/uploads"
  end

  include ::CarrierWave::Backgrounder::Delay
  include CarrierWave::MiniMagick

  storage :sftp

  # Override the directory where uploaded files will be stored.
  # This is a sensible default for uploaders that are meant to be mounted:
  def store_dir
    # "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
    "/"
  end

  def rotate(degree)
    manipulate! do |img|
      img.rotate(degree)
      img
    end
  end

  version :tiny, :if => :initial? do
    process :resize_to_fit => [75, 75]
    def full_filename(for_file = model.image.file)
      model.product_code.to_s + "-0.jpg"
    end
  end

  version :small, :if => :initial? do
    process :resize_to_fit => [200, 200]
    def full_filename(for_file = model.image.file)
      model.product_code.to_s + "-1.jpg"
    end
  end

  version :medium, :if => :initial? do
    process :resize_to_fit => [500, 500]
    def full_filename(for_file = model.image.file)
      model.product_code.to_s + "-2T.jpg"
    end
  end

  version :large, :if => :initial? do
    process :resize_to_fit => [1000, 1000]
    def full_filename(for_file = model.image.file)
      model.product_code.to_s + "-2.jpg"
    end
  end

  version :medium_alt, :if => :initial? do
    process :resize_to_fit => [100, 50]
    def full_filename(for_file = model.image.file)
      model.product_code.to_s + "-2S.jpg"
    end
  end

  version :medium_additional, :if => :additional? do
    process :resize_to_fit => [500, 500]
    def full_filename(for_file = model.image.file)
      model.product_code.to_s + "-#{model.version_number}" + "T.jpg"
    end
  end

  version :large_additional, :if => :additional? do
    process :resize_to_fit => [1000, 1000]
    def full_filename(for_file = model.image.file)
      model.product_code.to_s + "-#{model.version_number}" + ".jpg"
    end
  end

  version :medium_alt_additional, :if => :additional? do
    process :resize_to_fit => [100, 50]
    def full_filename(for_file = model.image.file)
      model.product_code.to_s + "-#{model.version_number}" + "S.jpg"
    end
  end

  version :ebay_initial, :if => :initial? do
    process :resize_to_fit => [1600, 1600]
    def full_filename(for_file = model.image.file)
      model.product_code.to_s + "-ebay.jpg"
    end
  end

  version :ebay_additional, :if => :additional? do
    process :resize_to_fit => [1600, 1600]
    def full_filename(for_file = model.image.file)
      model.product_code.to_s + "-#{model.version_number}" + "-ebay.jpg"
    end
  end

  version :display_initial, :if => :initial? do
    process :resize_to_fit => [200, 1000]
    def full_filename(for_file = model.image.file)
      model.product_code.to_s + "-display.jpg"
    end
  end

  version :display_additional, :if => :additional? do
    process :resize_to_fit => [200, 1000]
    def full_filename(for_file = model.image.file)
      model.product_code.to_s + "-#{model.version_number}" + "-display.jpg"
    end
  end

  protected

  def initial?(new_file)
    original_filename.to_i == 0
  end

  def additional?(new_file)
    original_filename.to_i > 0
  end

  # Add a white list of extensions which are allowed to be uploaded.
  # For images you might use something like this:
  # Currently inactive.
  # def extension_white_list
  #   %w(jpg jpeg)
  # end

end

Изображение.rb:

class Picture < ActiveRecord::Base

  mount_uploader :image, ImageUploader

  store_in_background :image

  belongs_to :item
end

Загрузка контроллера:

def import_pictures(pictures, item)
    pictures['image'].each do |a|
      if a.original_filename.downcase.include?('.jpg') || a.original_filename.downcase.include?('.jpeg')
        count = @item.pictures.count
        photo_number = count + 2
        a.original_filename = count.to_s
        @picture = @item.pictures.create(:image => a, :item_id => item.id, :product_code => item.product_code, :version_number => photo_number)
      else
        flash[:error] = "Only .jpg and .jpeg files are allowed. Try again."
        redirect_to edit_item_path(@item)
      end
    end
  end

Схема изображения:

create_table "pictures", force: true do |t|
    t.integer  "item_id"
    t.string   "image"
    t.datetime "created_at"
    t.datetime "updated_at"
    t.integer  "product_code"
    t.integer  "version_number"
    t.string   "image_tmp"
  end

Журналы Героку:

2015-03-19T20:27:56.804863+00:00 app[worker.1]: 2015-03-19T20:27:56+0000: [Worker(host:f84dfd71-bd05-4a44-ac83-1d1818d0bfe3 pid:3)] Job CarrierWave::Workers::StoreAsset (id=36) FAILED (5 prior attempts) with Errno::ENOENT: No such file or directory - /app/tmp/uploads/1426795849-9-9664/3

person Jack Pope    schedule 19.03.2015    source источник
comment
Как насчет использования process_in_background вместо этого? В документах говорится, что он был разработан для использования, когда у вас нет контроля над расположением кеша, такого как Heroku.   -  person Adam Cooper    schedule 21.05.2015
comment
Вы нашли способ сделать это?   -  person xecutioner    schedule 02.10.2015


Ответы (1)


На данный момент вы не можете использовать store_in_background на героку. Из README:

# Heroku may deploy workers on separate servers from where your dyno cached the files.
#
# IMPORTANT: Only use this method if you have full control over your tmp storage directory.

Таким образом, вы должны сохранять напрямую (без фоновой обработки) и можете обрабатывать_в_фоне с задержкой.

person Phil    schedule 25.08.2015