使用Paperclip、ImageMagick、Jcrop和S3存储进行裁剪:为什么'image.reprocess!'不会重新处理?

6
我(大致)遵循 RailsCasts教程#182,使用Paperclip,ImageMagick和Jcrop来允许上传的图像进行自定义裁剪。
由于我使用Amazon S3进行文件存储,因此我不得不重新调整教程的部分内容以适应。除了裁剪版本的图像未被重新处理(或该重新处理的结果未被重新上传到S3)之外,似乎一切都运行得很完美 - 因此,在裁剪过程之后,我仍然拥有最初上传的相同图像(对于我为每个图像存储的所有图像大小均如此)。
这是我的Feature(即Feature Image)模型:
class Feature < ActiveRecord::Base
  require "#{Rails.root}/lib/paperclip_processors/cropper.rb"

  attr_accessible    :image_file_name, :image
  attr_accessor      :crop_x, :crop_y, :crop_w, :crop_h
  after_update       :reprocess_image, :if => :cropping?

  if Rails.env == "production"
  S3_CREDENTIALS = { :access_key_id     => '<REDACTED>',
                     :secret_access_key => '<REDACTED>',
                     :bucket            => "<REDACTED>"}
  else
  S3_CREDENTIALS = { :access_key_id     => '<REDACTED>',
                     :secret_access_key => '<REDACTED>',
                     :bucket            => "<REDACTED>"}
  end

  has_attached_file :image,
                    :styles          => { :small => "240x135>", :croppable => "960x960>", :display => "960x540>" },
                    :processors      => [:cropper],
                    :storage         => :s3,
                    :s3_credentials  => S3_CREDENTIALS,
                    :path            => "features/:id/:style.:extension"

  validates_attachment_content_type :image, :content_type => ['image/jpeg', 'image/gif', 'image/png',
                                                              'image/pjpeg', 'image/x-png'], 
                                            :message => 'must be a JPEG, GIF or PNG image'

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

  def image_geometry(style = :original)
    @geometry ||= {}
    path = (image.options[:storage]==:s3) ? image.url(style) : image.path(style)
    @geometry[style] ||= Paperclip::Geometry.from_file(path)
  end

  private

  def reprocess_image
    image.reprocess!
  end
end

这是我的'cropper.rb'文件(Paperclip处理器):

module Paperclip
  class Cropper < Thumbnail
    def transformation_command
      if crop_command
        crop_command + super.sub(/ -crop \S+/, '')
      else
        super
      end
    end

    def crop_command
      target = @attachment.instance
      if target.cropping?
        " -crop '#{target.crop_w}x#{target.crop_h}+#{target.crop_x}+#{target.crop_y}'"
      end
    end
  end
end

我的FeaturesController的相关操作:
class FeaturesController < ApplicationController

  def new
    @feature = Feature.new
  end

  def create
    @feature = Feature.new(params[:feature])
    if @feature.save
      if params[:feature][:image].blank?
        flash[:notice] = "New feature added!"
        redirect_to @feature
      else
        render :crop
      end
    else
      @title = "Add a New Feature"
      render :new
    end
  end

  def edit
    @feature = Feature.find(params[:id])
    @title = "Edit #{@feature.headline}"
  end

  def update
    @feature = Feature.find(params[:id])
    if @feature.update_attributes(params[:feature])
      if params[:feature][:image].blank?
        flash[:notice] = "Feature updated!"
        redirect_to @feature
      else
        render :crop
      end
    else
      @title = "Edit Feature"
      render :edit
    end
  end
end

我 'crop.html.erb' 视图文件中相关的代码行:

<% content_for :javascript_includes do %>
    <%= javascript_include_tag 'jquery.Jcrop.min' %>
    <script type="text/javascript" charset="utf-8">
    $(function() {
        $('#cropbox').Jcrop({
            onChange: update_crop,
            onSelect: update_crop,
            setSelect: [0, 0, 960, 540],
            aspectRatio: 960/540
        });
    });

    function update_crop(coords) {
        var ratio = <%= @feature.image_geometry(:original).width %> / <%= @feature.image_geometry(:croppable).width %>;
        $("#crop_x").val(Math.round(coords.x * ratio));
        $("#crop_y").val(Math.round(coords.y * ratio));
        $("#crop_w").val(Math.round(coords.w * ratio));
        $("#crop_h").val(Math.round(coords.h * ratio));
    };
    </script>
<% end %>
<% content_for :style_includes do %>
    <%= stylesheet_link_tag 'jquery.Jcrop', :media => 'screen' %>
<% end %>

<%= image_tag @feature.image.url(:croppable), :id => "cropbox" %>

<% form_for @feature do |f| %>
    <% for attribute in [:crop_x, :crop_y, :crop_w, :crop_h] %>
        <%= f.hidden_field attribute, :id => attribute %>
    <% end %>
    <p><%= f.submit "Crop" %></p>
<% end %>

问题不在于自定义剪裁(偏移、剪裁区域等)出现错误,而是当我点击“剪裁”时没有任何剪裁发生 - 我只得到了从原始上传/处理中获得的图像。似乎根本没有发生“image.reprocess!”(或重新处理的结果没有保存到S3)。可能的原因是什么,我该怎么办?
3个回答

3

2

好的,让我来帮助你 :)

首先,不要在模型中包含您的Paperclip处理器,让Paperclip来处理它。

其次,删除:after_update并替换为:before_update,这应该为您的处理器设置image.options[ :crop ]。在您的处理器中,请尝试以下操作:

def initialize file, options = {}, attachment = nil
  super
  #......

  @crop = options[ :crop ]

  #......

第三步,在处理器中修改你的transformation_command
def transformation_command
  if @crop
      trans = " -quality 75"
      trans << " -crop \"#{<YOUR_CODE>}\" +repage" if @crop
      trans
  end
end

接着发布您的发现 :)


是的!我遇到了与原问题提出者相同的问题,您建议将 after_update 更改为 before_update,这为我解决了问题。非常感谢! - Gabe Durazo

0

我也使用了同样的RailsCast视频来帮助我实现裁剪。我遇到了一个类似的问题,NOSUCHKEY错误,我能够追踪到是在after_update之后调用了reprocessing!方法导致的。我使用了Vish的答案并进行了修改来解决这个问题。我的解决方案可能不完全符合你的需求,因为我每次都进行裁剪。

我只是删除了对reprocess!的after_update调用,并保留了其他所有内容。这会导致传递给处理器(在你的情况下是cropper)而不是默认处理器,并且发生在将图像上传到S3之前。由于你在第一次上传之前就裁剪了文件,所以一切正常!

如果你想要有条件的裁剪,那么你需要做Vish建议的事情,即在before_update中设置一个变量或传递一个选项与图像对象一起使用。它需要在你的自定义处理器中可用,这样你就可以根据它的值放置你的条件裁剪逻辑。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接