Webアプリ開発エンジニアのための技術情報サイト「テックスコア」

3. ファイルアップロード

2006.08.09 株式会社四次元データ 岡本和也

本章ではこれまでの章において構築してきた Web アプリケーションにファイルアップロード機能を追加します。

これまで日記形式の Web アプリケーションを構築してきましたが、画像が無いために少し寂しい感じがするのでは ないでしょうか。そこで、画像ファイルのアップロードと表示を行いたいと思います。一般的に画像情報はテキスト情報に比べて 大きくなりますので、データベースに画像ファイルを格納するのはお勧めできません。そこで、データベースには 画像ファイルの位置情報を保持させることにします。では、MySQL にアクセスして画像ファイルの位置情報を格納する列を追加 しましょう。下記のコードをコマンドラインで実行してください。

$ mysql -u root -p
Enter password: ****

mysql> use diary
Database Changed

mysql> alter table items add
    -> picture_url varchar( 100 )
    -> ;

これでテーブルに画像ファイルの位置情報を格納する列を1つ追加することができました。次に、\app\views\items にある new.rhtml ファイルを書き換えます。このファイルには新しい記事を追加する際のインタフェースが記述されています。

 1:<form action="create" method="post" enctype="multipart/form-data">
 2:  <p>
 3:    <b>Title:</b><br />
 4:    <%= text_field "item", "title", "maxlength" => 20 %>
 5:  </p>
 6:  <p>
 7:    <b>Text:</b><br />
 8:    <%= text_area "item", "text", "cols" => 40, "rows" => 8 %>
 9:  </p>
10:  <p>
11:    <b>Picture:</b><br />
12:    <%= file_field "file", "picture", "size" => 60 %>
13:  </p>
14:  <p><input type="submit" value="投稿" /></p>
15:</form>
16:<%= link_to 'Back', :action => 'list' %>

1行目では multipart/form-data 形式で post メソッドによりデータを送信すると指定しています。 これは複数の form 入力データを複数データとして送るために指定しています。
4行目の text_field は Ruby on Rails で提供されている1行の入力フォームです。 ここではタイトルの長さを20に制限していますが、テーブルを作成する際に、タイトル列は varchar 型で 長さ100文字(つまり、100バイト)の設定をしていますので、50以下に制限しておけば問題ありません。 また、text_field の2番目と3番目の引数により、フォームに入力された値を item というオブジェクトの title 要素として 渡すと宣言しています。8行目と12行目のフォームも同じような仕組みになっています。
8行目の text_area は text_field の入力フォームが複数行となったものです。
12行目の file_field は入力フォームの横に参照ボタンを伴い、アップロードしたいファイルを選択することができます。 ファイルそのものは file オブジェクトの picture 要素として渡すと宣言しています。

次に、コントローラファイルを書き換えましょう。\app\controllers\items_controller.rb の create メソッドを書き換えます。
下記に書き換え後の \app\controllers\items_controller.rb の一部を記します。

 1:def create
 2:  @item = Item.new(params[:item])
 3:  @item.postingdate = Time.now
 4:  @filename = params[:file]['picture'].original_filename
 5:  if @filename != "" then
 6:    @item.picture_url = "http://localhost:3000/images/" + @filename
 7:    Item.save(params[:file]['picture'])
 8:  end
 9:  if @item.save
10:    flash[:notice] = 'Item was successfully created.'
11:    redirect_to :action => 'list'
12:  else
13:    render :action => 'new'
14:  end
15:end

変更点は4行目から8行目を追加したことです。まず、4行目で file オブジェクトの picture 要素に入っているファイル情報に アクセスして original_filename 操作でファイル名を調べ、@filename 変数に格納しています。5行目はファイル名が あればという条件になっていますが、日記の記事を投稿する際にファイルが指定されていれば6, 7行目を行う という意味になります。6行目では指定ファイルがアップロードされる場所をテーブルの picture_url 列に入れるよう 指定しています。(実際の格納命令は9行目の @item.save です。)アップロードファイルは内部的には \public\images フォルダに アップロードされます(格納フォルダは後で指定します)が、外部的には /images/ 以下にアップロードされますので、 6行目のように指定しておきます。7行目で Item モデルに対してファイルをアップロードするように指示しています。
そこで、モデルファイルの書き換えも行います。\app\models\item.rb ファイルを書き換えましょう。

1:class Item < ActiveRecord::Base
2:  def self.save(file)
3:    File.open("public/images/#{file.original_filename}", "wb"){ |f| f.write(file.read) }
4:  end
5:end

2行目から4行目を追加しました。簡単に説明しますと、2行目において引数として file という情報の集合を受け取っています。 さらに、3行目で \public\images\[アップロードファイル名] の場所を書き込み可能なバイナリ形式でアクセス可能にし、 ファイル情報を書き込んでいます。

以上の操作によりファイルのアップロードが完了しました。最後に画像ファイルを見れるようにビューファイルを書き換えます。 \app\views\items\list.rhtml ファイルを以下のように書き換えてください。

 1:<h1>ブログ</h1>
 2:<%= link_to 'New item', :action => 'new' %>
 3:<hr />
 4:<% @items.each do |@item| %>
 5:  <h3><%= @item.title %></h3>
 6:  <%= @item.text %>
 7:  <br />
 8:  <% if @item.picture_url != nil then %>
 9:    <p><img src="<%= @item.picture_url %>" alt="picture"></p>
10:    <br />
11:  <% end %>
12:  <%= @item.postingdate %>
13:  <br />
14:  <%= link_to 'Show', :action => 'show', :id => @item.id %>
15:  <%= link_to 'Edit', :action => 'edit', :id => @item.id %>
16:  <%= link_to 'Destroy', { :action => 'destroy', :id => @item.id }, :confirm => 'この記事を消去していいですか?', :post => true %>
17:  <br />
18:  <hr />
19:<% end %>

8行目から11行目を追加しました。8行目の if 文により items テーブルの picture_url 列に値が無い場合は、 画像ファイルの表示を行いません。値がある場合は、9行目でその値を用いてアップロードファイルにアクセスして、 画像ファイルとして表示させます。

画像ファイルを表示させることができたでしょうか。次章ではメールを使って記事の投稿を行えるようにします。



前のページへ TECHSCOREのTOPページへ 次のページへ
techscore(トップページへ)
TECHSCORE書店
TECHSCOREトップページJavaSQLXMLリッチクライアントモデリングセマンティックWebその他技術Tuigwaa