【ruby on rails】image_uploadプラグイン
画像をかっこよくアップロードするプラグインImageUploadを使ってみた。
ImageUpload:
http://imageupload.rubyforge.org/
参考:
http://cookpad.typepad.jp/lt/2007/12/image_upload621_947f.html
http://ko.meadowy.net/~nay/?image_upload%A5%D7%A5%E9%A5%B0%A5%A4%A5%F3
特徴:
画像の情報(パスやサイズ等)は独立したテーブルで管理し、他のモデルとポリモーフィック関連で関連づけられるので既存の親マスタに対して柔軟に設計可能。インタフェースは、ajaxを利用してファイル選択と同時にファイルをアップロードしプレビューでき、複数の画像を同時に操作できる(非ajaxインタフェースもあり)。画像アップロード字に画像の回転が行える。画像データは任意のディレクトリに保存し任意のフォルダから画像データを取得するヘルパーがある。
その他:
RMagickが必要。
いい感じで動きます。
アップロードした画像とそのサムネイルを出力する機能が欲しかったので弄ってみた。プラグインを触るのは大変そうなので画像データのActiveRecordモデルであるstored_fileモデルを弄って対応した。
# The base stored file class.
class UserImage < ActiveRecord::Base
belongs_to :attachable, :polymorphic => true
acts_as_list :scope => :attachable
attr_accessor :buffer, :tmp_file, :thumbnail
after_destroy :delete_file
THUMBNAIL_WIDTH = 40
THUMBNAIL_HEIGHT = 40
NORMAL_PATH = '/normal/'
THUMBNAIL_PATH = '/thumbnail/'
validates_presence_of :name, :unique_key
def ext
self.name =~ /.*\.(.*)$/
$1
end
# Set the uploaded buffer.
# This is useful for uploading without Ajax I/F.
def buffer=(buffer)
@buffer = buffer
return unless buffer?
self.name = buffer.original_filename
self.unique_key = genkey()
end
# Returns true if the buffer is valid.
def buffer?
@buffer && @buffer != "" && @buffer.original_filename.length > 0
end
def tmp_file=(tmp_file)
@tmp_file = tmp_file
return unless @tmp_file
self.name = tmp_file[:name]
self.unique_key = genkey()
end
# You can change this if you want to use another name pattern.
def change_thumbnail
self.thumbnail = true
self.width = THUMBNAIL_WIDTH
self.height = THUMBNAIL_HEIGHT
end
def stored_file_path
# File.join(path, stored_name)
if self.thumbnail == true
stored_file_path_thumbnail
else
stored_file_path_normal
end
end
def image_path
return $1 if stored_file_path.match(/public\/images\/(.*)$/)
nil
end
def scale_down_size(max_width, max_height)
return [nil, nil] unless self.width && self.height
h = height.to_f / max_height.to_f
w = width.to_f / max_width.to_f
return [self.width, self.height] if (h <= 1 && w <= 1)
m = h >= w ? h : w
return [(self.width.to_f / m).to_i, (self.height.to_f / m).to_i]
end
protected
def before_save
self.stored_name = create_file_name
end
def before_create
if @tmp_file
File::open(@tmp_file[:path], 'rb') do |fh|
update_file_attributes(i = ImageSize.new(fh))
i.close # for windows
end
else
update_file_attributes(ImageSize.new(@buffer))
end
end
def after_create
# FileUtils.makedirs(path) unless File.exist?(path)
FileUtils.makedirs(path + NORMAL_PATH) unless File.exist?(path + NORMAL_PATH)
FileUtils.makedirs(path + THUMBNAIL_PATH) unless File.exist?(path + THUMBNAIL_PATH)
if @tmp_file
FileUtils.mv(@tmp_file[:path], stored_file_path_normal)
raise "Couldn't move #{@tmp_file[:path]}" unless File.exist?(stored_file_path_normal)
resize_and_write_image(stored_file_path_normal, stored_file_path_thumbnail)
# delete original tmp file (if exists)
File.delete(@tmp_file[:original_tmp_path]) if @tmp_file[:original_tmp_path] && File.exist?(@tmp_file[:original_tmp_path])
@tmp_file = nil
else
store_buffer
@buffer.close # Avoid TempFile's garbage collection problem (exception arount closed stream).
@buffer = nil
end
end
private
# Create file_name from unique_key.
# Some file name (ex. using Japanese) can't be displayed properly by some OS.
# And, this can disturb users to image and try other file names.
def create_file_name(ext = nil)
ext ||= self.ext
return name unless ext
"#{unique_key}.#{ext}"
end
# Store the file in the file system.
def store_buffer
return unless buffer?
@buffer.binmode
File.open(stored_file_path_normal, "w") do |f|
f.binmode
f.write(@buffer.read)
resize_and_write_image(stored_file_path_normal, stored_file_path_thumbnail)
end
end
# Delete the file from the file system.
def delete_file
# File.delete(stored_file_path)
File.delete(stored_file_path_normal) if FileTest.exist?(stored_file_path_normal)
File.delete(stored_file_path_thumbnail) if FileTest.exist?(stored_file_path_thumbnail)
end
# You can overwrite this.
def path
"#{RAILS_ROOT}/attached_files/user_images"
end
GENKEY_MAX_TRY = 10
def exsit_key?(key)
UserImage.find(:first, :conditions => ['unique_key = ?', key]) ? true : false
end
def genkey
salt = [rand(64),rand(64)].pack("C*").tr("\x00-\x3f","A-Za-z0-9./")
n = 0
key = nil
begin
raise "genkey_max_try over." if n == GENKEY_MAX_TRY
key = "#{Time.now.strftime('%Y%m%d%H%M%S').crypt(salt).tr(' /.', '___')}-#{n}"
n += 1
end while exsit_key?(key)
key
end
def update_file_attributes(image_size)
raise "no ImageSize" unless image_size
self.mime_type = image_size.mime_type
if size = image_size.get_size
self.width = size[:width]
self.height = size[:height]
else
self.width = nil
self.height = nil
end
self.thumbnail = false
end
def stored_file_path_thumbnail
File.join(path, THUMBNAIL_PATH + stored_name)
end
def stored_file_path_normal
File.join(path, NORMAL_PATH + stored_name)
end
def resize_image(img, width, height)
return true if img.columns <= width && img.rows <= height
begin
require 'RMagick'
img.resize_to_fit!(width, height)
return true
rescue Exception => e
return false
end
end
def resize_and_write_image(source, dest)
begin
result = true
require 'RMagick'
img = ::Magick::Image::read(source).first
if resize_image(img, THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT)
img.write(dest)
else
result = false
end
img = nil
enabled_gc = GC.enable
GC.start
GC.disable if enabled_gc
return result
rescue Exception => e
return false
end
end
end
かなりいけてない修正になった感があるが、まあいいとしよう。
このログへのコメント(0件)
コメント投稿フォーム
トラックバック
関連ログ
- 【ruby on rails】submit_tagに確認ダイアログをつける方法
- 【ruby on rails】file_columnを使った画像ファイルのアップロード
- 【ruby on rails】railsのHTMLヘルパーに悩む
- 【ruby on rails】acts_as_authenticatedで認証
- 【ruby on rails】rubyでRSSを生成する。
- 【ruby on rails】改行コードをBRコードに変換するには
- 【ruby on rails】start_form_tag / form_tag
- 【ruby on rails】link_toヘルパーにclassを指定するには
- 【ruby on rails】rake db:migrate
- rubyでのメールアドレスとURLを抽出する正規表現
