This is my first code dealing with uploads and rmagick, so please comment if you have suggestions.
class DbFile < ActiveRecord::Base
IMAGE_TYPES = ['image/jpeg', 'image/pjpeg', 'image/gif', 'image/png', 'image/x-png']
before_validation :sanitize_filename
validates_presence_of :size, :filename, :content_type
class << self
def new_file(file_data)
content_type = file_data.content_type.strip
(IMAGE_TYPES.include?(content_type) ? DbImage : DbFile).new \
:data => file_data.read,
:filename => file_data.original_filename,
:size => file_data.size,
:content_type => content_type
end
end
protected
def sanitize_filename
# NOTE: File.basename doesn't work right with Windows paths on Unix
# get only the filename, not the whole path
filename.gsub! /^.*(\\|\/)/, ''
# Finally, replace all non alphanumeric, underscore or periods with underscore
filename.gsub! /[^\w\.\-]/, '_'
end
end
require 'rmagick'
require 'base64'
class DbImage < DbFile
def data=(file_data)
with_image(file_data, true) do |img|
self.width = img.columns
self.height = img.rows
end
end
def with_image(file_data = nil, save_image = false, &block)
img = Magick::Image::read_inline(Base64.b64encode(file_data || self.data)).first
block.call(img)
write_attribute('data', img.to_blob) if save_image
img = nil
GC.start
end
end
Controller Usage:
# returns DbImage if content_type matches
db_file = DbFile.new_file(params[:file][:data])
db_file.save
Model Usage:
# raw binary image data
File.open('my_file', 'w') { |f| f.write(db_file.data) }
# Image resizing with rmagick
# automatically creates RMagick::Image and
# invokes GC.start
db_file.with_image do |img|
img.scale(.25)
img.write('thumb.jpg')
end
文章来源: http://snippets.dzone.com/posts/show/793