2008年6月30日月曜日

Rails:画面遷移無しでファイルアップロード



■画面遷移無しでファイルアップロード
Railsでファイルアップロードを行うには、FORMを下記のように準備すれば、

<%= form_tag({:action=>'upload'},:multipart=>true) %>
<%= file_field 'attached_file', 'attached_file','size'=>29 %>

file = params[:attached_file]で受け取り、file.readをFileなりDB格納できますが、FORMで他のテキストを編集させる兼ね合いでページ遷移を発生させたくありませんでした。

■通常のFORMタグでAjax風の操作感を実現
RailsにはAjaxに対応したform_remote_tagがありますが、残念ながら:multipartの指定ができません。セキュリティ上の制約によりjavascript ではローカルファイルへのアクセスができないからだそうです。

■responds_to_parent
そこでresponds_to_parentを利用してみることにしました。
コントローラでresponds_to_parent利用することで、サーバ側からページを制御することができます。

ruby script/plugin install http://sean.treadway.info/svn/plugins/responds_to_parent/



■リクエストの作成
通常のFORMを生成するstart_form_tagを使いますので、:multipart=> trueを指定できます。

<%= start_form_tag ({:action => 'attach_file'},
{:id =>"att_form",
:multipart=> true,
:target=> "dummy_frame",
:onsubmit=>"submit();Form.disable('main_form');return false;"}) %>
<%= end_form_tag %>

Javascriptでsubmitし、targetを同rhtmlファイル内に配置したダミーのiframeにすることで、画面遷移せずにリクエスト送信可能になります。

<iframe id='none' name="dummy_frame" style="display:none;" src=<%= url_for(:action=>'dummy_action') %>></iframe>


■レスポンスの作成
コントローラでレスポンスを制御しますが、必要なパラメタオブジェクトなどを生成後、renderなどする代わりにresponds_to_parentを利用します。
下記の例では、rhtml内の
<div id="div_attachedfile">hoge</div>
の部分を_attachedfile.rhtmlで更新した上で、disableだったmain_form,cancel_formの2つのFORMを有効にしています。

responds_to_parent do
render :update do |page|
page.replace_html('div_attachedfile',
:partial=>"attachedfile",
:object=>@attached_files)
page << "Form.enable('main_form');Form.enable('cancel_form');"
end
end


■iframeでsrc指定が無いとSSLページでセキュリティ警告が発生します
上記のiframeタグの例で、src=<%= url_for :action=>"dummy_action" %>を指定し、コントローラにてこれに対応した下記のアクションを作成しています。

def dummy_action
render(:nothing=>true)
end


これがないとIEでSSLページを表示した際に、
このページにはセキュリティで保護されている項目と保護されていない項目が含まれています。保護されていない項目を表示しますか?

という警告メッセージが出てかなりウザいことになります。
iframeでSRC 属性を指定しないと発生するということですのでsrcを指定すればよいのですが、当然これに対応したサーバ側リソースが必要ですので、上記のようにdummy_actionを作成しました。


■参考
Ajaxっぽく画面遷移なしでファイルアップロードしたい!
Ruby on Rails: ファイルアップロード機能を作る
[PRB] FRAME/IFRAME を含むページを SSL により参照するとセキュリティ警告メッセージが発生する




0 件のコメント: