fc2ブログ

Sinatraで画像アップロードとダウンロード

追記.2012/02/26
このソースの完成形です。
Sinatraで画像のCRUD

Sinatraで画像のアップロードとダウンロードを作ってみました。
データの保存はMongoidを使っています。
Mongoidでは、保存前にRMagickで解析してフォーマットとサイズと取得して保存しています。
ダウンロードではサムネイルを使用しています。もしサムネイルでは無く実データを表示するときは、image.dataを使用すればOKです。

app.rb
#coding: utf-8
require 'sinatra/base'
require './models/image'

class MyApp < Sinatra::Base
configure do
set :haml, {format: :html5}

Mongoid.configure do |conf|
conf.master = Mongo::Connection.new('localhost', 27017).db('test')
end
end

get '/upload' do
haml :upload
end

post '/upload' do
if params[:data]
file = params[:data][:tempfile]
image = Image.new(name: params[:name], data: file.read(file.length))
image.save
redirect '/view?id=' + image._id.to_s + '&w=100&h=100'
else
haml :upload
end
end

get '/view' do
image = Image.first(conditions: {_id: params[:id]})
content_type image.content_type
image.thumbnail(params[:w], params[:h])
end
end

views/upload.haml
!!! 5
%head
%body
%h1 Upload

%form{action: '/upload', method: 'post', enctype:'multipart/form-data'}
%input{type: 'text', name: 'name'}
%br
%input{type: 'file', name: 'data'}
%br
%input{type: 'submit', value: 'Upload'}

models/image.rb
#coding: utf-8
require 'mongoid'
require 'RMagick'

class Image
include Mongoid::Document
include Mongoid::Timestamps
field :name
field :data
field :format
field :width, type: Integer
field :height, type: Integer

before_save :to_data
after_initialize :from_data

# コンテントタイプ
def content_type
'image/' + format.downcase
end

# サムネイル作成
def thumbnail(w, h)
img = Magick::Image.from_blob(data).first
img.thumbnail!(calc_scale(w.to_i, h.to_i))
img.to_blob
end

# スケール計算
def calc_scale(w, h)
if width > height
scale = w / width.to_f
scaled_height = height * scale
if scaled_height > h
scale = h / height.to_f
end
else
scale = h / height.to_f
scaled_width = width * scale
if scaled_width > w
scale = w / width.to_f
end
end
scale
end

protected
def to_data
img = Magick::Image.from_blob(data).first
self.format = img.format
self.width = img.columns
self.height = img.rows
self.data = BSON::Binary.new(data, BSON::Binary::SUBTYPE_BYTES)
end

def from_data
self.data = data.to_s
end
end
スポンサーサイト



COMMENTS

COMMENT FORM

TRACKBACK


この記事にトラックバックする(FC2ブログユーザー)