ファイルアップロード

今まで何度となくファイルアップロードを書いては忘れ、その都度調べてて、いい加減疲れてきたのでここにメモる。今後はここをコピペする方向で。

基本的にこちらのコピーなので、要respond_to_parentプラグイン。説明もそちらを参照。ここには単にコードだけ置いときます。

できることは、画面遷移無しのファイルアップロードと、フォームの下に表示されているファイルリストの非同期な更新。

テーブルはこんな感じ

class CreateUploadedFiles < ActiveRecord::Migration 
  def self.up
    create_table :uploaded_files do |t|
      t.column :filename, :string
      t.column :content_type, :string
      t.column :size, :integer                      
      t.column :data, :binary                       
      t.column :created_at, :integer                
    end                                             
  end                                               
                                                    
  def self.down                                     
    drop_table :uploaded_files                      
  end                                               
end                                                 

ビュー
アップロードフォームを持つ静的な部分と、動的に更新されるファイルリストはテンプレートを分けておく

attach.rhtml

<iframe name="frame" style="width:0;height:0;border:0;"></iframe>                                                   
<% form_tag({:action => 'upload'}, 
            {:multipart => true, :target => 'frame'}) do -%> 
 <%= file_field_tag 'file' %>                                                                         
 <%= submit_tag _('Upload') %>                                                                        
<% end -%>                                                                                            
                                                                                                      
<div id='uploaded_file_list'>                                                                         
 <%= render :partial => 'uploaded_file_list' %>                                                       
</div>                                                                                                

_uploaded_file_list.rhtml

<% unless @uploaded_files.empty? -%>           
 <ul>                                                   
 <% @uploaded_files.each do |uploaded_file| -%>
  <li><%= uploaded_file.filename %></li>                
 <% end -%>                                             
 </ul>                                                  
<% else -%>                                             
 <%= _('No uploaded file exists.') %>                   
<% end -%>                                              

コントローラー

def attach
  @uploaded_files = UploadedFile.find :all
end

def upload
  file = params[:file]
  UploadedFile.create :filename => file.original_filename,
                      :content_type => file.content_type,
                      :size => file.length,
                      :data => file.read
  @uploaded_files = UploadedFile.find :all
  responds_to_parent do
    html = render_to_string :partial => 'uploaded_file_list'
    render :update do |page|
      page.replace_html 'uploaded_file_list', html
    end
  end
end

[追記]
画面遷移なしでファイルアップロードする方法 と Safariの注意点 (groundwalker.com) にかかれてあるとおりの現象がおきたので修正しました。