さて、これを行う方法を理解しました。以下で説明します。私の勘は、2つの異なるCarrierWaveアップローダークラスを使用するのが正しかったです。1つはS3へのアップロード専用のクラス(CarrierWave_Direct gemを使用)、もう1つは画像処理専用のクラス(私がすでに本番環境で使用していたクラス)です。以下に関連するコードを投稿してみますが、質問がある場合はお知らせください。なぜこのような別々のクラスを使用している他の人を見たことがないのかわかりませんが、それは私にとってはうまくいくようです。
app\uploaders\image_uploader.rb
carrierwave_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
。
- 写真コントローラーで、ImageUploaderクラスの@uploader変数を作成します。これは、@ uploaderを使用するインデックス/ビューフォームで送信された画像が、画像を「temp」フォルダーにアップロードすることを意味します。これは、ImageUploaderクラスを使用するためです。この画像がアップロードされると、処理は行われません(まだ)。
- ユーザーがフォームの[アップロード]ボタンをクリックすると、[写真]>>[作成]アクションが呼び出されます。このアクションは@photo.save_and_process_imageを呼び出します-モデルを見て、このメソッドが実際にS3'temp'フォルダーから最近アップロードされた画像を取得し、それを処理してから、処理された画像を最終的な宛先に再アップロードすることを確認します。私の写真モデルは、処理/アップロードを行うImageProcessorクラスにリンクされているため、これはすべて可能です。別のImageUploaderクラスにはリンクされていません。
これが私が何をしているのかを説明するのに役立つことを願っています