Ruby on Rails3でファイルを直接アップロード

今回はファイルのアップロードですが、データベースにではなく直接ファイルを流します。
そのため管理者であるということを条件として作成していきます。
ですのでadministratorは管理者であるという意味です。
そしてadministrator内にfileを作成し、その中にnew.html.erbとdone.html.erbを作成します。

まずはroutes.rbの作成です。管理者になっている(ログインしている)という意味のcollection
にget内にdoneとnewを追加します。
今回使うファイルはdone.html.erbとnew.html.erbだけなのでこれだけです。

new自体はお決まりのindex,new,show,edit,createの中に入っているので指定する必要はないのですが、indexがないためnewに直接飛ばすという意味で指定しました。

resources :files do
   get :done, :new, :on => :collection
end

次にコントローラーです。見た感じcreateしか指定していません。doneとnewは空で結構です。
●まずupload = params[:upload_image]でパラメーターを指定します。
●次にunless params[:upload_image].blank?でパラメーターが空でないか調べます
●そして@filename = save_image_file(upload)と@filename = save_file(upload)は@filenameに
情報を入れています。save_image_fileもsave_fileもモデルなどで作ります。(今回はpravate指定のコントローラー内で作成)
●render :action => :doneでdoneに飛ばしています。
flash[:warning] = 'ファイル名が空です'はunless以外の時にメッセージを出します。
●redirect_to params[:from] || :administrator_filesはメッセージ出力後redirect_toでnewに飛ばしています

class Administrator::FilesController < Administrator::Base
  def new  
  end

  def create
    unless params[:upload_image].blank?
      upload = params[:upload_image]
      @filename = save_image_file(upload)
      render :action => :done
      return
    end
    unless params[:upload_file].blank?
      upload = params[:upload_file]
      @filename = save_file(upload)
      render :action => :done
      return
    end
    flash[:warning] = 'ファイル名が空です'
    redirect_to params[:from] || :administrator_files
  end

  def done
  end

次にsave_image_fileとsave_fileを作成します。プログラムが多くなる場合モデルに書いた方がいいのですが今回はpravate指定をしてコントローラーで作成しました。

●original_filenameは送られてきたファイル情報からファイル名だけを取り出す処理です
●unless upload.original_filename.blank?はファイルが空ではないという条件
●送られるファイル情報をfilenameとする
●送られて来ているファイルの送信先をfiledirとする
●送られたファイルをjoinでファイル・パスの区切り文字を気にしないでRubyがうまくつなげる処理
●f = File.open(filepath, "wb")はファイル操作を行うという意味で"wb"はw=writeでb=バイナリを意味しその書き込み先がfilepathである
●f.write(upload.read)は中身を読みそれをファイルに書き込む作業
●save_fileもsave_image_fileも行き先が違うだけで内容は同じです

  private
  def save_image_file(upload)
    unless upload.original_filename.blank?
      filename = upload.original_filename
      filedir = "public/images/abcd_self"
      filepath = File.join(filedir,filename)

      f = File.open(filepath, "wb")
      f.write(upload.read)
      f.close

      return filename
    end
  end
  
  def save_file(upload)
    unless upload.original_filename.blank?
      filename = upload.original_filename
      filedir = "app/views/abcd/abcd_self"
      filepath = File.join(filedir,filename)

      f = File.open(filepath, "wb")
      f.write(upload.read)
      f.close

      return filename
    end
  end
end

次にようやくnewの作成です。

●<% if flash[:warning] -%><%= flash[:warning] %><% end -%>で空の時のメッセージを出します。
●<%= form_tag [ :administrator, :files ], :multipart => true do %>〜<% end %>でフォームの作成です。administrator内のfilesであるということです
●<%= file_field_tag 'upload_image' %>はファイルを参照するフィールドです
●<%= submit_tag "アップロード" %>でアップロードボタンの作成です

これでイメージ用とファイル用二つ作りました。空の場合上にメッセージも出力されます。

<h2>ファイルアップロード</h2>

<% if flash[:warning] -%>
<p id="warning"><%= flash[:warning] %></p>
<% end -%>

<%= form_tag [ :administrator, :files ], :multipart => true do  %>
  画像ファイルを選択して下さい:(*.jpg, *.gif, ...)<br/>
  <%= file_field_tag 'upload_image' %><br/>
  <%= submit_tag "アップロード" %><br/>
<% end %>
<br/>
<%= form_tag [ :administrator, :files ], :multipart => true do  %>
  テンプレートファイルを選択して下さい:(*.html.erb)<br/>
  <%= file_field_tag 'upload_file' %><br/>
  <%= submit_tag "アップロード" %><br/>
<% end %>
<br/>

最後にファイルを受け取るdoneの作成です。

●ファイル名:<%= @filename %>はコントローラーで指定した@filename = save_image_file(upload)と@filename = save_file(upload)なので、ファイル名が出力されます。
●<%= link_to 'アップロードを続ける', :administrator_files %>でnewに戻って何度もアップロードできます。

<h1>アップロードしました</h1>
ファイル名:<%= @filename %>
<br/>
<p><%= link_to 'アップロードを続ける', :administrator_files %></p>

以上でアップロードができました。