[导入]generic file and image models for uploaded files

These are basic models that store a file in a dedicated files table. Use has_one or has_many to associate this with your actual models. RMagick is required for images.

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

你可能感兴趣的:(generic)