画像のアップロード

業務用アプリのことは、ひとまず置いといて。
今回は Rails で画像ファイルをアップロードする方法を調べてみました。これは、自然観察のフィールドノートを写真付きで管理するアプリには必須の機能です(そんなソフトは作らない?)。

file_column Plugin をインストール

ネットをググッてみたら、file_column なるプラグインが良いらしい。というか、殆どデファクト・スタンダードです? これ一つでファイルのアップロード、表示から、リサイズまでこなしてくれるみたいです。
これは、RMagick を利用するらしい。で、RMagick は、ImageMagick の Ruby 用ラッパー(?)です。ということは、
  1. ImageMagick をインストール
  2. RMagick をインストール
  3. file_column Plugin をインストール
と、段階の手順を踏んではじめて使えるようになります。結構面倒です。
しかしめげずに、それぞれの最新版を落としてきて入れたところ、見事エラーが表示され、動きませんでした。
むむむ。むむむむむ。さらに調べる。
答えは、RMagick ページのFAQに、ありました。
I've got a version of ImageMagick for Windows that is more recent than the bundled version. Can I use it?

No. You must use the ImageMagick Windows installer that is bundled with RMagick even if a later version is available from ImageMagick. RMagick will not run if you try to use a different version.
どうやら、RMagick は ImageMagick のバージョンを選ぶらしいです。
指示に従って、RubyForge の RMagick プロジェクトページから、無難そうな RMagick-1.14.1_IM-6.3.0-7-Q8.zip を落としてきます。
解凍して、README.HTML を読みます。

なになに。
まず、"ImageMagick のインストーラを起動せよ。Update executable search path.オプションをチェックだぞ。あとのオプションはお前に任せる"、か。ラジャーっす。
ここにも、"他バージョンの ImageMagick は使うでない"と書いてあります。

続いて、RMagick のインストールです。こちらは gem を使います。
gem install rmagick --local
"Successfully installed rmagick, version 1.14.1" とか、表示されたら完了です。

やれやれ。ようやく本題の file_column Plugin の番です。
が、これは簡単。お馴染みの RadRails で、Rails Plugins タブを選び、file_column Plugin を選択してインストールすれば完了です。

file_column Plugin を使ってみる

環境を整えるまでにちょっとありましたが、これで使えるようになりました。早速、画像ファイルのアップロード機能を実現しましょう。
ああ、その前に一つ確認事項です。
file_column Plugin では、画像ファイルは所定のディレクトリに入れられ、テーブルには画像ファイルへのパスが保存されます。まあ、一般的な方式ですね。
では、テーブルに、パスを保存するフィールドを追加しましょう。
今回は、pictures テーブルに String 属性の image という名前のフィールドを作りました。
RadRails で、/app/models/picture.rb を開き、次のように書き加えます。
class Picture < ActiveRecord::Base
 file_column :image, :magick => {
   :versions => {
    :thumb => "100x100",
    :middle => "200x200",
    :large => "800x800"
   }
  }

end
image というフィールドに画像ファイルのパスを入れるよ、という設定です。
見ての通り、オリジナル画像の他に、"thumb"、"middle"、"large"という3種類のサイズの画像も保存します。これは別に3種類じゃなくても、また、名称もサイズも自由に設定できます。
リサイズには RMagick(ImageMagick) が使われます。ジャギーが目立ちませんので、リサイズメソッドはバイリニアかバイキュービック法でしょうかね。済みません、調べていません。

view にアップロード機能を付け加えるのも簡単です。
<form action="create" method="post" enctype="multipart/form-data">
 <p>
  <b>画像ファイル:</b><br />
  <%= file_column_field "picture", "image" %>
 </p>
 <p><input type="submit" value="アップロード" /></p>
</form>
アップロードした画像を表示させるには、
<%= image_tag url_for_file_column(@picture, 'image') %>
の様にします。これはオリジナルサイズの画像表示用です。リサイズされた画像を表示させるには、
<%= image_tag url_for_file_column(@picture, 'image', :thumb) %>
の様に指定します。

いやぁ、実に簡単にアップロード機能が実装できました。アップロード時に、拡張子、ファイルサイズ、画像サイズなどのバリデーションも可能です。小さすぎる画像や大きすぎる画像をハネるのも簡単ですね。

日本語のファイル名を使えるようにする

と、ここまでは良かったんですが。……2バイト文字のファイル名が使えません。漢字はアンダーバーに置き換えられてしまいます。
日本語のファイル名は色々と問題を起こすから、ここは思い切って禁止!!と、してしまうのもテですが、それもナニですので、2バイト文字使用可にしましょう。
それには、file_column Plugin をいじります。
file_column Plugin は、/vendor/plugins/trunk にインストールされています。さらに、lib ディレクトリの中を見ると、file_column.rb というファイルがありますので、RadRails でこれを開きます。
すずーっとスクロールしていくと、一番終わりに、
 def self.sanitize_filename(filename)
  filename = File.basename(filename.gsub("\\", "/")) # work-around for IE
  filename.gsub!(/[^a-zA-Z0-9\.\-\+_]/,"_")
  filename = "_#{filename}" if filename =~ /^\.+$/
  filename = "unnamed" if filename.size == 0
  filename
 end
という部分があります。
ファイル名のサニタイジングをしていますね。filename.gsub!(/[^a-zA-Z0-9\.\-\+_]/,"_")の部分は、ファイル名に含まれる半角英数字以外をアンダーバーに置き換えます。どうやらここで2バイト文字がハネられている様です。
サニタイジングはセキュリティに係わる部分ですが、思い切って書き換えます。
  filename.gsub!(/[^\w\.\-\+_]/,"_")
これだけです。
これで2バイト文字も通して貰えるようになります。メデタシ、メデタシ。

……って、WindowsXP のフォルダに、ファイル名 UTF-8 で書かれちゃうのね。変換ロジック書くのもめんどいし、ま、いっか(ちゃんとしたい人は、勝手に変換して下さい。または、Linux かなんかで、ファイルシステムを UTF-8 にして運用して下さい――って、ダメ?)。


file_column Plugin の弱点は、ドキュメント類の少なさではないか、と勝手に思うわけです。
/vendor/plugins/trunk/lib で、

rdoc

と打てばドキュメントが出てきますが、英語だし、もうちょっと何とかして欲しいです。
誰か、インターネット上に豊富なサンプルコード付きでマニュアル公開してくれないかなぁ。もち、日本語で。






サイト名: flyman のおもちゃ箱   http://www.kestrel.jp
この記事のURL:   http://www.kestrel.jp/modules/tinyd04/index.php?id=4