今回は、Ruby on RailsからS3へファイルをアップロードしてみたいと思います。
RailsにはPaperclipというファイルアップロードプラグインがあり、Marcel Molina Jr.さん謹製のAWS::S3というgemを使用したS3へのアップロードもサポートしているのですが、今回はせっかくAmazonの公式ruby sdkが公開されたので、そちらを利用したPaperclip拡張である@igor-alexandrovさんのpaperclip-awsを使用してS3ファイルアップロードを試してみます。

Paperclipは、ImageMagickを使用するので、まずImageMagickをインストールします。
yumからだとバージョンが古い場合があるので、ソースからインストールします。

# cd /usr/local/src
# wget ftp://ftp.imagemagick.org/pub/ImageMagick/ImageMagick.tar.gz
# tar xzvf ImageMagick.tar.gz
# cd ImageMagick-6.7.1-2
# ./configure
# make
# make install

次にldconfigでライブラリの更新をシステムに知らせます。

# ldconfig /usr/local/lib

Gemfileに以下のgemをインストールします。

  • RMagick(ImageMagickのRubyラッパー)
  • Paperclip(ファイルアップロードプラグイン)
  • paperclip-aws(PaperclipでのS3アップロード機能拡張)
$ vi Gemfile
gem 'rmagick'
gem "paperclip", "~> 2.3"
gem "papepclip-aws"

gemのインストールと更新を行います。

$ bundle install vendor/bundle
$ bundle update

ImageMagickへのパスを通します。

$ vi config/environments/development.rb 
Paperclip.options[:command_path] = "/usr/local/bin/"

RailsでScaffoldを作成してみます。
今回は、簡易ブログを作成する想定でblogというモデルのScaffoldを作成しました。

$ rails g scaffold blog title:string description:text

モデルにファイルアップロードの項目を追加します。

Paperclipのhas_attacched_fileメソッドの引数では、デフォルトのPaperclipの項目以外にpaperclip-awsで追加されたs3用の項目も指定できます。
尚、項目についてはModule: Paperclip::Storage::S3で解説されています。

ここでは、photoという名前で追加し、S3ってなんじゃ?(RUBY SDK鈍行編1 ruby on railsの準備)の設定でaws.ymlにアクセスキーとシークレットキーしか設定していなかったので、今回、その他の設定は直接指定していますが、これらもaws.ymlに含めることもできます。
以下、コメントで追加部分を明記してあります。

$ vi app/models/blog.rb
class Blog 
######追加部分 ここから######
 def self.s3_config
   @@s3_config ||= YAML.load(ERB.new(File.read("#{Rails.root}/config/aws.yml")).result)[Rails.env]
 end

 has_attached_file :photo,
                   :styles => {
                     :thumb => [">75x"],
                     :medium => [">600x"]
                   },
                   :storage => :aws,
                   :s3_credentials => {
                     :access_key_id => self.s3_config['access_key_id'],
                     :secret_access_key => self.s3_config['secret_access_key'],
                     :endpoint => 's3-ap-northeast-1.amazonaws.com'
                   },
                   :s3_bucket => 'myfirst-bucket',
                   :s3_host_alias => self.s3_config['s3_host_alias'],
                   :s3_acl => :public_read,
                   :s3_protocol => 'http',
                   :path => "images/:id/:style/:data_file_name"
######追加部分 ここまで######

end

続いて、viewに画像ファイルの項目を追加します。
viewは、通常のPaperclipのviewの書き方と同様で、まずは、入力画面にphoto属性のファイル選択フィールドを追加します。

$ vi app/views/blogs/_form.html.erb
######追加部分###### , :html => { :multipart => true }
{ :multipart => true } ) do |f| %>

prohibited this blog from being saved:



######追加部分 ここから######

######追加部分 ここまで######

詳細画面や完了画面で写真が確認できるようにphotoのimgタグを追加します。

$ vi app/views/blogs/show.html.erb

Title:

Description:

######追加部分###### |

一覧画面にサムネイルを表示するようにサムネイル用のimgタグを追加します。

$ vi app/views/blogs/index.html.erb

Listing blogs

Title Description Photo
'Are you sure?', :method => :delete %>

次に、Paperclip用の項目をDBに追加するためのマイグレーションファイルを作成します。

$ rails g migration add_photo_columns_to_blog
     invoke  active_record
     create    db/migrate/20110805111437_add_photo_columns_to_blog.rb
$ vi db/migrate/20110805111437_add_photo_columns_to_blog.rb 
class AddPhotoColumnsToBlog 
 def self.up
   add_column :blogs, :photo_file_name,    :string
   add_column :blogs, :photo_content_type, :string
   add_column :blogs, :photo_file_size,    :integer
   add_column :blogs, :photo_updated_at,   :datetime
 end

 def self.down
   remove_column :blogs, :photo_file_name
   remove_column :blogs, :photo_content_type
   remove_column :blogs, :photo_file_size
   remove_column :blogs, :photo_updated_at
 end

end

マイグレーションを行います。

$ rake db:migrate
(in /var/www/html/myfirstcloud)
==  CreateBlogs: migrating ====================================================
-- create_table(:blogs)
  -> 0.0011s
==  CreateBlogs: migrated (0.0014s) ===========================================

==  AddPhotoColumnsToBlog: migrating ==========================================
-- add_column(:blogs, :photo_file_name, :string)
  -> 0.0007s
-- add_column(:blogs, :photo_content_type, :string)
  -> 0.0004s
-- add_column(:blogs, :photo_file_size, :integer)
  -> 0.0005s
-- add_column(:blogs, :photo_updated_at, :datetime)
  -> 0.0004s
==  AddPhotoColumnsToBlog: migrated (0.0028s) =================================

これで、S3にアップロードすることができるようになりましたので、ブラウザで確認してみます。

http://IPアドレス/blogs

上記にアクセスすると、以下のようにscaffoldで作成された一覧画面が表示されます。

New Blogのリンクをクリックして、新規登録画面を表示すると、画像アップロードのフィールドがあることが確認できます。
そして、テキストを入力し、画像を選択したらCreate Blogボタンをクリックします。

すると、登録完了の画面として、アップロードした写真が表示されます。

また、一覧画面に戻ると、一覧にもサムネイルが表示されているのがわかります。

表示されている画像のURLを見ると以下のようにS3からホストされていることが確認できます。

http://s3-ap-northeast-1.amazonaws.com/myfirst-bucket/images/1/thumb/:data_file_name

このように、簡単にS3ファイルアップロードを実装することができました。

こちらの記事はなかの人(memorycraft)監修のもと掲載しています。
元記事は、こちら