载波如何重新处理原始文件

时间:2018-08-21 20:05:47

标签: ruby-on-rails ruby carrierwave

我已经更新了载波上传器,以将图像大小限制为2000px。我没有使用任何自定义版本。我想重新处理之前已上传的所有图像。我尝试使用.recreate_version!,但这似乎不起作用。我还能做些什么吗?

上载器

class FileUploader < CarrierWave::Uploader::Base
  include CarrierWave::MiniMagick

  delegate :extension_whitelist, to: :model

  process resize_to_fit: [2000, 2000]

  def filename
    # CarrierWave has already defined @filename
    @_filename ||= generate_random_filename
  end

  def generate_random_filename
    return unless file = model.file&.file

    3.times do
      name = "#{SecureRandom.hex(6)}.#{file.extension}"
      return name unless Attachment.search(file_url_end: name).result.any?
    end

    fail "couldn't find a unique filename!"
  end

  def url(options = {})
    mounted_on = model.send(:_mounter, mounted_as).uploader_options[:mount_on] || mounted_as

    if model.attributes[mounted_on.to_s] =~ /https?:\/\/.+/
      model.attributes[mounted_on.to_s]
    else
      super
    end
  end
end

附件

class Attachment < ApplicationRecord
  has_paper_trail

  belongs_to :owner, polymorphic: true

  mount_uploader :file, FileUploader,
    # `mount_on` is used to get around a paper_trail bug where it tries serializing the
    # uploader object, instead of simply the URL itself.
    # https://github.com/modernmsg/modernmsg/pull/2847#issuecomment-199378461
    # http://stackoverflow.com/questions/9423279
    mount_on: :file_url

  # Stores the full URL in the database
  def write_uploader(column, identifier)
    if file._storage == CarrierWave::Storage::AWS
      identifier = CarrierWave::Storage::AWSFile.new(file, file.send(:storage).connection, file.store_path).url
    end

    write_attribute(column, identifier)
  end

  PURPOSES = {
    ...
  }

  MIN_WIDTHS = {
    ...
  }

  validates_inclusion_of :purpose, allow_nil: true, in: -> a { PURPOSES[a.owner.class] || [] }

  # CarrierWave normally starts processing the file immediately as the attribute is set.
  # That's a problem because `extension_whitelist` is determined by the association,
  # which isn't set until after the attributes themselves are set.
  # https://github.com/carrierwaveuploader/carrierwave/issues/361
  # https://github.com/rails/rails/blob/v4.2.5.2/activerecord/lib/active_record/associations/has_many_association.rb#L34-L43
  # rubocop:disable Style/TrivialAccessors
  alias original_file= file=
  def file=(file)
    @file = file
  end
  before_validation :set_file
  def set_file
    self.original_file = @file if @file
  end
  # Then, for the remote URL option
  alias original_remote_file_url= remote_file_url=
  def remote_file_url=(url)
    @remote_file_url = url
  end
  before_validation :set_remote_file_url
  def set_remote_file_url
    self.original_remote_file_url = @remote_file_url if @remote_file_url
  end
  # rubocop:enable Style/TrivialAccessors

  # Don't accidentally override the file if other attributes are updated.
  skip_callback :save, :before,  :write_file_identifier,         unless: :file_url_changed?
  skip_callback :save, :after,   :store_file!,                   unless: :file_url_changed?
  skip_callback :commit, :after, :remove_previously_stored_file, unless: ->{ previous_changes.key? :file_url }

  validates_presence_of :file

  def extension_whitelist
    images = %w[jpg jpeg gif png svg]
    videos = %w[mov mp4]
    promotional_materials = %w[pdf]

    case owner
    when Authentication, Property, Company
      images + promotional_materials
    when Ad
      images + videos
    when User, Profile, Player
      images
    end
  end

  validate :check_min_width
  def check_min_width
    if min_width && file?
      width, height = FastImage.size file.path
      if width < min_width
        errors.add :purpose, "min width for a #{purpose} image is #{min_width} pixels"
      end
    end
  end

  def min_width
    MIN_WIDTHS.dig owner.class, purpose
  end
end

耙任务

# CarrierWave rake tasks
#
# Task:   reprocess
# Desc:   Reprocess all images for the Attachment class
# Usage:  rake carrierwave:reprocess

namespace :carrierwave do
  desc 'Reprocess all images for the Attachment class'
  task reprocess: :environment do
    Attachment.all.each do |a|
      a.file.recreate_versions!
      a.save!
    rescue
      false
    end
  end
end

1 个答案:

答案 0 :(得分:0)

为了重新处理,您将需要创建版本。对于CarrierWave,即使您在FileUploader中添加了全局resize_to_fit转换,也永远不会重新处理原始文件。

要实现所需的功能,可以创建一个新版本。我将其命名为large

class FileUploader < CarrierWave::Uploader::Base
  include CarrierWave::MiniMagick

  # ...

  version :large do 
    process resize_to_fit: [2000, 2000]
  end
end

您现在可以运行rake任务。当您查看S3文件夹时,您将意识到每个上载文件都有两个文件。一个是原始版本,另一个是large版本。