4

そのため、Amazon s3に保存された画像を含むcarrierwave gemを使用して、すでにサイトを運用しています。私のアップローダは、このstore_dirメソッドを使用して、処理済みの画像に入れる特定の構造を指定します。

さて、私の開発環境では、carrierwave_direct gem を追加して、S3 への直接アップロードを開始しました。問題は、この gem がアップローダーの store_dir とファイル名のデフォルトを完全に上書きすることです。古い画像リンクがすべて壊れてしまうため、完全に機能するアップローダーをライブにプッシュすることはできません。

CWdirect gem が生の画像ファイルを S3 の「一時」ディレクトリにアップロードすると、S3 が応答してkey変数を提供するので、このファイルを取得して必要に応じて処理できると理解しています。それで、画像を処理して正しいフォルダに配置するために、carrierwave で完全に別の画像アップローダ クラスを使用する必要がありますか? つまり、この宝石がアップロードしたいと思われる場所ならどこにでもアップロードする、carrierwave_direct 専用のアップローダーを 1 つ用意します。現在の store_dir とファイル名の構造を維持する、実際のモデルにリンクされた別の uploader.rb クラスを使用しますか?

いずれにせよ、私の基本的な質問は、特定のフォルダー構造内の画像を使用して実稼働環境で CW を既に実行している場合、どのように CarrierWave_Direct gem を使用できるかということです。

4

1 に答える 1

6

さて、これを行う方法を理解しました。以下で説明します。私の勘は、2つの異なるCarrierWaveアップローダークラスを使用するのが正しかったです。1つはS3へのアップロード専用のクラス(CarrierWave_Direct gemを使用)、もう1つは画像処理専用のクラス(私がすでに本番環境で使用していたクラス)です。以下に関連するコードを投稿してみますが、質問がある場合はお知らせください。なぜこのような別々のクラスを使用している他の人を見たことがないのかわかりませんが、それは私にとってはうまくいくようです。

app\uploaders\image_uploader.rbcarrierwave_direct gemを利用した私の画像アップローダークラス:

class ImageUploader < CarrierWave::Uploader::Base
  include CarrierWaveDirect::Uploader

  include ActiveModel::Conversion
  extend ActiveModel::Naming

  include CarrierWave::MimeTypes
  process :set_content_type

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

  # Include the Sprockets helpers for Rails 3.1+ asset pipeline compatibility:
  include Sprockets::Helpers::RailsHelper
  include Sprockets::Helpers::IsolatedHelper

  # Override the directory where uploaded files will be stored.
  # CarrierWaveDirect::Uploader puts raw uploaded files in this directory on S3 as a first step
  def store_dir
    "unprocessed_uploads"
  end
end

**このクラスでは処理が行われていないことに注意してください

私の画像処理クラスapp\uploaders\image_processor.rb(すでに本番環境で実施されていたもの):

class ImageProcessor < CarrierWave::Uploader::Base

  # Include RMagick or MiniMagick support:
  # include CarrierWave::RMagick
  include CarrierWave::MiniMagick
  include CarrierWave::MimeTypes
  process :set_content_type

  # Include the Sprockets helpers for Rails 3.1+ asset pipeline compatibility:
  include Sprockets::Helpers::RailsHelper
  include Sprockets::Helpers::IsolatedHelper

  # Choose what kind of storage to use for this uploader:
  storage :fog

  # 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}"
    # "uploads/#{model.class.to_s.underscore}/path/#{model.id}"
  end

  # Provide a default URL as a default if there hasn't been a file uploaded:
  def default_url
    "logos/" + [version_name, "default.png"].compact.join('_')
  end

  # Process files fetched from S3 after they are uploaded:

  def make_thumbnail(width, height)
    # uses MiniMagick classes to get a square, centered thumbnail image
    manipulate! do |img|
      if img[:width] < img[:height]
        remove = ((img[:height] - img[:width])/2).round
        img.shave("0x#{remove}")
      elsif img[:width] > img[:height]
        remove = ((img[:width] - img[:height])/2).round
        img.shave("#{remove}x0")
      end

      img.resize("#{width}x#{height}")
      img
    end        
  end


  # Create different versions of your uploaded files:
  # the process statement below isn't defined within a version block on purpose--this means the ORIGINAL uploaded photo is constrained to 1050 pics
  process :resize_to_limit => [1050, 1050]
  process :quality => 85 # this reduces filesize greatly and saves space

  version :thumb do
    process :make_thumbnail => [100, 100]
    process :quality => 85 # this reduces filesize greatly and saves space
  end

  version :big_thumb do
    process :make_thumbnail => [350, 350]
    process :quality => 85 # this reduces filesize greatly and saves space
  end

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

  # Override the filename of the uploaded files:
  # Avoid using model.id or version_name here, see uploader/store.rb for details.
  def filename
    if original_filename
      if model && model.read_attribute(:image).present?
        model.read_attribute(:image)
      else
        "#{secure_token}.#{file.extension}"
      end
    end
  end

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

end

私の写真モデル(要約):

class Photo < ActiveRecord::Base
  mount_uploader :image, ImageProcessor

  def save_and_process_image(options = {})
    s3_unprocessed_image_url = self.image.asset_host + '/' + self.key
      # this next line downloads the image from S3
      # and this save line below will process the image and reupload to S3 according to ImageProcessor settings
      self.remote_image_url = s3_unprocessed_image_url
      save
  end

end

フォトコントローラーとビューコードも利用できます。必要に応じてお知らせください。基本的に、ImageUploaderクラスを使用して、S3への最初のアップロードをunprocessed_uploadsというフォルダーに実行します。次に、S3は、ImageProcessorクラスに渡すURLのフィールドで応答しkeyます。これは、写真に添付され、サムネイルやその他の画像を処理してから、S3のアップロードフォルダーに再アップロードします。

この分離により、carrierwave_direct gemを追加するときに、S3の現在のフォルダー構造を変更する必要がなくなりました。これが他の人に役立つことを願っています。もっとコードが必要な場合は教えてください私はタイプするのにうんざりしています:)

更新-コードの追加:

写真コントローラー:

class PhotosController < ApplicationController

  def index
    @photos = @photos.sort_by(&:created_at)

    @uploader = ImageUploader.new
    @uploader.success_action_redirect = new_tank_photo_url(@tank)

    respond_to do |format|
      format.html # index.html.erb
      format.json { render json: @photos }
    end
  end

  def create
    respond_to do |format|

      if @photo.save_and_process_image
        format.html { redirect_to tank_photos_path(@tank), notice: 'Photo uploaded successfully and is being processed...' }
        format.json { render json: @photo, status: :created, location: @photo }
      else
        format.html { render :new }
        format.json { render json: @photo.errors, status: :unprocessable_entity }
      end
    end
  end

写真のインデックスビュー、[アップロード]ボタンのあるフォーム:

    <%= direct_upload_form_for @uploader, :html => {:class => "form-inline"} do |f| %>
        <%= f.file_field :image %>
        <%= f.submit "Upload", :class => "btn btn-primary btn-medium" %>
    <% end %>

したがって、上記のビュー/コントローラーコードを追加して、実行した手順の概要を以下に示します。ImageUploaderクラスとクラスの違いに注意してくださいImageProcessor

  1. 写真コントローラーで、ImageUploaderクラスの@uploader変数を作成します。これは、@ uploaderを使用するインデックス/ビューフォームで送信された画像が、画像を「temp」フォルダーにアップロードすることを意味します。これは、ImageUploaderクラスを使用するためです。この画像がアップロードされると、処理は行われません(まだ)。
  2. ユーザーがフォームの[アップロード]ボタンをクリックすると、[写真]>>[作成]アクションが呼び出されます。このアクションは@photo.save_and_process_imageを呼び出します-モデルを見て、このメソッドが実際にS3'temp'フォルダーから最近アップロードされた画像を取得し、それを処理してから、処理された画像を最終的な宛先に再アップロードすることを確認します。私の写真モデルは、処理/アップロードを行うImageProcessorクラスにリンクされているため、これはすべて可能です。別のImageUploaderクラスにはリンクされていません。

これが私が何をしているのかを説明するのに役立つことを願っています

于 2013-02-12T22:13:18.493 に答える