【问题标题】:File does not get stored (mounted) if processing of versions fails如果版本处理失败,文件不会被存储(挂载)
【发布时间】:2018-10-19 14:20:01
【问题描述】:

我将 carrierwave 从 0.11.0 升级到 1.2.3 并意识到,对我来说至关重要的是,行为已经改变并打破了我的逻辑。这是我的上传器的示例。

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

  storage :fog

  version :thumb do
    process :convert => :jpg

    def default_url
      '/assets/document_thumb.png'
    end
  end

end

还有它安装的模型:

class Material < ActiveRecord::Base

  attr_accessible :name, :file

  mount_uploader :file, FileUploader, validate_processing: false

  before_create :create_file_hash

  def create_file_hash
    self.hash_digest = Digest::MD5.hexdigest(file.read)
  end

end

在旧的carrierwave中,即使版本处理(例如在这种情况下转换)失败,文件的主要版本仍会被上传和存储。但是,现在在处理失败的情况下(并非总是如此,但我不能进行条件处理,因为我的情况比这里说明的更复杂)没有任何内容被存储。 file 属性仍然是一个空的(空白)上传器,并且没有任何内容上传到雾存储。

知道如何恢复旧的行为吗?

换句话说,如何忽略处理版本的任何错误。或者不在after_cache 回调中触发版本处理,而是在稍后的某个时间触发?

我认为我已经将此问题追溯到Mounter#cache 方法的以下更改:

def cache(new_files)
  return if not new_files or new_files == ""
  @uploaders = new_files.map do |new_file|
    uploader = blank_uploader
    uploader.cache!(new_file)
    uploader
  end

  @integrity_error = nil
  @processing_error = nil
rescue CarrierWave::IntegrityError => e
  @integrity_error = e
  raise e unless option(:ignore_integrity_errors)
rescue CarrierWave::ProcessingError => e
  @processing_error = e
  raise e unless option(:ignore_processing_errors)
end

过去只是直接执行uploader.cache!(new_file)(不在地图中),然后uploader 一路更新并在需要时返回模型。但是,现在处理错误导致地图块退出,@uploaders 数组永远不会被有效的上传器更新(即原始文件)。

【问题讨论】:

  • 忘记包含我在贴片机上确实拥有的validate_processing: false 选项。从某种意义上说,模型验证不会失败并且模型确实会被保存。只是没有上传者。

标签: carrierwave ruby-on-rails-4.2 fog


【解决方案1】:

一种可能的解决方案是在您的上传器中覆盖 cache! 方法:

class FileUploader < CarrierWave::Uploader::Base
  def cache!(*)
    super
  rescue CarrierWave::ProcessingError => e
    Rails.logger.debug "FileUploader: Error creating thumbnail: #{e}"
    nil
  end
  ...
end

这样,它适用于每个模型

【讨论】:

    【解决方案2】:

    经过半天的努力,这是我提出的不涉及猴子修补载波的解决方案。

    class Material < ActiveRecord::Base
    
      attr_accessible :name, :file
    
      mount_uploader :file, FileUploader, validate_processing: false      
    
      #----> This is to manually trigger thumbnail creation <----
      before_create :create_thumbnail
    
      def create_thumbnail
        file.thumb.cache!(file.file)
      rescue CarrierWave::ProcessingError => e
        Rails.logger.debug "FileUploader: Error creating thumbnail: #{e}"
      end
    
      # rest of the model code
    end
    

    所以这里我们在before_create 回调中触发了create_thumbnail 方法,该回调手动调用thumb 上传器上的cache! 方法。 file.file此时(即在创建之前,因此在文件上传到存储之前)指向临时缓存文件。这正是我们想要的(我们不想为了创建缩略图而从存储中重新下载文件。

    class FileUploader < CarrierWave::Uploader::Base
      include CarrierWave::MiniMagick
    
      storage :fog
    
      #----> Add the if condition to versions <----
      version :thumb, if: :has_versions? do
        process :convert => :jpg
    
        #----> This is needed to trigger processing later <----
        after :cache, :process!
    
        def default_url
          '/assets/document_thumb.png'
        end
      end
    
      #---> This is to avoid versions before the main version is fully processed and cached <---
      def has_versions?
        !(model.new_record? && model[:file].nil?)
      end
    
    end
    

    现在这是棘手的聚会。我们需要首先禁用版本创建,因此我们有has_versions? 方法来检查文件是否是新记录。现在检查还不够,因为在我们的before_create 回调中,模型仍然是新记录(即它还没有被持久化)。

    但是,上传者第一次尝试创建版本(如果失败,会阻止原始文件缓存,如问题中所述)和我们在 before_create 回调中调用它的那一刻有什么区别是在第二种情况下会设置模型的file属性。

    但是要小心,因为您不能执行model.file,因为它指向上传器(如果在此处调用我调用它的位置,它实际上会导致堆栈溢出)。您需要以model[:file] 的身份访问它。

    最后一个技巧是,出于某种原因,仅在模型中调用 cache! 不会真正触发处理。该处理应该在初始运行期间触发(我们阻止了其他版本),并且由于原始文件被缓存,carrierwave 预计版本也是如此,因此它们不需要处理。但是添加after :cache, :process! 可以确保它被触发。

    不知道是否有人会发现这很有用,或者我是否以错误的方式解决了这个问题。

    不管怎样,我很想听听 cmets。

    很高兴我让它适用于我的情况,并且我可以继续使用最新的 gem 版本。

    【讨论】:

    • 鉴于此解决方案的复杂性以及它仍然依赖于cache! 方法的事实,我更喜欢猴子补丁,因为它直截了当且简短。这个解决方案“在纸上”更清晰,但复杂性更高,更难解释(从评论量来看)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-07
    • 2020-08-12
    • 1970-01-01
    • 2017-12-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多