RMagic::Image#thumbnail!
強いなぁ、これ。例外処理省略して書くとこんな感じで、ajax っぽいuploader作りました。
ポイントは、dummy フレームを使って、multipartのフォームをpostする点と、画像の表示更新にURIクエリでタイムスタンプを付与しているところ。タイムスタンプを付与しないと、ブラウザがローカルキャッシュにあるものを表示しちゃうのです。
<table style="text-align:center"> <tbody> <tr> <td> <form target="dummy" action="<%= direct_url_for :action => 'upload_photo' %>" enctype="multipart/form-data" method="post" > <input type="file" name="photo" size="70"/> <input type="submit" value="send" /> </form> </td> </tr> </tr> <td id="<%= my_dom_id('photo') %>" style="padding:1em;"> <img src="/component/system/account_photo/download_photo/<%= @account.id %>" /> </td> </tr> </tbody> </table> <iframe id="dummy" name="dummy" style="display:none"></iframe>
require 'RMagick' include Magick class System::AccountSettingsController < ApplicationController uses_component_template_root is_widget (snip) def upload_photo photo = params[:photo].read photo = Image.from_blob(photo)[0] if photo.columns > 120 || photo.rows > 120 # resize image scale_factor = photo.columns > photo.rows ? (120.0 / photo.columns) : (120.0 / photo.rows) photo.thumbnail!(scale_factor) end @account.photo = photo.to_blob @account.photo_type = params[:photo].content_type.gsub(/\r/, '') @account.save time = Time.now responds_to_parent do render :update do |page| page << "Element.update('#{widget_instance.dom_id('photo')}', '<img src=\"/component/system/account_photo/download_photo/#{@account.id}?#{time.strftime('%y%m%d%H%M%S')}\" />')" end end end end
class System::AccountPhotoController < ApplicationController uses_component_template_root def download_photo user = WjUser.find(params[:id]) if user.photo opts = { :filename => "user_#{user.id}_photo", :type => user.photo_type, :disposition => 'inline' } send_data user.photo, opts else # TODO prepare the photo when the user data is not set. render :nothing => true end end end