ruby-on-rails - 使用 CarrierWave 和 MiniMagick 进行 Rails 裁剪并上传到 S3

标签 ruby-on-rails carrierwave

我在这方面已经有一段时间了。使用这个 RailsCast我已经能够修改它以与 CarrierWave 一起工作——至少在理论上是这样。我试图让用户裁剪他们的个人资料照片,然后使用 CarrierWave 将其上传到 S3。到目前为止,这是有效的:

  • 用户上传一张图片以及其他个人资料信息
  • 他们被成功带到裁剪页面,在那里他们可以裁剪照片 - 照片已上传并成功捕获原始图像尺寸
  • 单击“裁剪”以保存图像不会触发任何错误(模型保存得很好),但据我所知也不会实际裁剪或重新创建版本。

所以,这是我得到的代码。这是模型:

attr_accessor :crop_x, :crop_y, :crop_w, :crop_h, :original_width, :original_height
attr_accessible :avatar, :remove_avatar
after_update :reprocess_avatar, :if => :cropping?

mount_uploader :avatar, ProfileBaseUploader

def cropping?
  !crop_x.blank? && !crop_y.blank? && !crop_w.blank? && !crop_h.blank?
end

private
  def reprocess_avatar
    avatar.process!
    avatar.recreate_versions!
  end

漂亮的样板 - crop_x 等属性是从裁剪 View 中分配的。我已确认这些已正确传递和分配,并且正在调用 reprocess_avatar 方法。

这是我的上传代码:

include CarrierWave::MiniMagick
include CarrierWaveDirect::Uploader

storage :fog

require 'guid'

process :cropper
process :store_best_geometry

version :tiny_thumb do
  process :resize_to_limit => [50, 50]
end

version :thumb do
  process :resize_to_limit => [200, 200]
end

version :large do
  process :resize_to_fit => [500, 500]
end

def extension_white_list
    %w(jpg jpeg gif png)
end

def filename
   @name ||= "#{secure_token}.#{file.extension}" if original_filename.present?
end

def store_best_geometry
  manipulate! do |img|
    if model
      model.original_width = img['width']
      model.original_height = img['height']
    end
    img = yield(img) if block_given?
    img
  end
end

def cropper
  return unless model.cropping?
  manipulate! do |img|
    img = img.crop("#{model.crop_x}x#{model.crop_y}+#{model.crop_w}+#{model.crop_h}")
    img
  end
end

protected
  def secure_token
    var = :"@#{mounted_as}_secure_token"
    model.instance_variable_get(var) or model.instance_variable_set(var, Guid.new)
  end

认为那个过程!并重新创建版本!方法根本无法正常运行,但我不知道为什么。我没有任何可以提供的错误(如果有人知道我如何生成错误,我会很乐意这样做)。我知道 store_best_geometry 方法效果很好。不能对 cropper 说同样的话。

有什么想法吗?

最佳答案

就像一次严重的飞机失事,有很多事情我做错了。

首先,我对 crop 的论证顺序错误。在我的问题中,您会注意到我有:

img.crop('[x offset]x[y offset]+[width]+[height]')

正确的顺序是:

img.crop('[width]x[height]+[x offset]+[y offset]')

所以这是第一个问题。尝试以错误的顺序执行此操作会抛出一个错误(深入控制台找到它)关于所提供的几何图形无效。

下一个问题:用我的裁剪方法打破 yield 链并返回字符串而不是图像。原来 crop 方法返回一个字符串。看原来的cropper方法:

def cropper
  return unless model.cropping?
  manipulate! do |img|
    img = img.crop("#{model.crop_x}x#{model.crop_y}+#{model.crop_w}+#{model.crop_h}")
    img
  end
end

糟糕!最后返回的是一个字符串。事实证明,正确的方法是直接调用图像上的方法:

def cropper
  return unless model.cropping?
  manipulate! do |img|
    img.crop("#{model.crop_w}x#{model.crop_h}+#{model.crop_x}+#{model.crop_y}")
    img = yield(img) if block_given?
    img
  end
end

我做错的最后一件事——这是一个完全业余时间的错误——没有让一些关键属性可访问。以我无限的智慧,我假设 attr_accessor 将使属性可访问。没有。我必须修改我的模型以使 crop_x、crop_y、crop_w 和 crop_h 参数可访问。

attr_accessor :crop_x, :crop_y, :crop_w, :crop_h, :original_width, :original_height
attr_accessible :avatar, :remove_avatar, :crop_x, :crop_y, :crop_w, :crop_h
after_update :reprocess_avatar, :if => :cropping?

最后一点,不重要但很容易知道。我不需要调用进程!作为 recreate_versions!为我做的。

希望这至少能帮助到一个人。

关于ruby-on-rails - 使用 CarrierWave 和 MiniMagick 进行 Rails 裁剪并上传到 S3,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10791554/

相关文章:

ruby-on-rails - 我如何查看模型是否有带有 Carrierwave 的照片?

ruby-on-rails - Carrierwave 和 has_many

ruby-on-rails - 如何加快在 Google Cloud Platform 上部署 Rails Docker?

ruby-on-rails - 如何确定字符串是否为数字?

ruby-on-rails - Ruby:无法分配内存

file-upload - 使用 Rails 4、强参数和 Carrierwave 上传文件

ruby-on-rails - 将 base64 图像转换为用于 Carrierwave 的 StringIO

ruby-on-rails - 通过 Regex、Ruby 拆分时保留模式字符

ruby-on-rails - 没有路由匹配 [GET] "/logout"?

javascript - 在 Rails 中操作上传的 svg 文件