LoginSignup
1
3

More than 5 years have passed since last update.

Railsのform_tagでS3に画像をアップロードする機能を作った話

Last updated at Posted at 2018-06-09

2018/06/09 記事を作成

はじめに

Ruby on Railsでよく使うformと言えば form_for ですね。
このformは扱うデータが何かしらのModelに基づいていることを前提としていますが、S3等のクラウドストレージにデータを保存したい場合、Modelを作らないという選択肢もあるかと思います。
そこで form_for ではなく form_tag でformを作ろうと思ったのですが、筆者が調べた範囲では form_tag でS3にデータをアップロードする的な記事はあんまりありませんでした。
そこで、今回筆者が実装した内容を以下に簡単にまとめようと思います。
この記事がどこかの誰かさんの参考になれば幸いです。

環境

OS: Ubuntu 16.04 LTS
ブラウザ: Chromium 66.0.3359.181(Official Build)Built on Ubuntu

S3とは

Amazon Simple Storage Service はインターネット用のストレージサービスです。また、ウェブスケールのコンピューティングを開発者が簡単に利用できるよう設計されています。

Amazon S3 のウェブサービスインターフェイスはシンプルで、いつでも、ウェブのどこからでも容量に関係なくデータを格納および取得できます。これにより、すべての開発者が、スケーラブルで信頼性が高く、かつ高速で安価なデータストレージインフラストラクチャを利用できるようになります。このインフラストラクチャは、Amazon が使用しているウェブサイトのグローバルネットワークと同じものです。このサービスの目的は、規模の拡大や縮小のメリットを最大限に活かし、開発者に提供することです。

Amazon S3 とは何ですか? - Amazon Simple Storage Serviceより引用)

※本記事ではS3のバケットは既にあるものとして話を進めます。

実装

View

Viewはこんな感じ。
Slimで記述しています。

image_upload.html.slim
= form_tag({:action => "upload_image"}, :multipart => true) do
  = file_field_tag :file, accept: 'image/jpg,image/jpeg,image/png'
  = submit_tag "アップロード"

ここで重要なのは、multipartオプションを省略しないことです。
form_for では省略しても大丈夫なのですが、 form_tag の場合は省略してしまうとファイル名が文字列として渡るだけでファイル本体が取得できません。

ちなみに、 file_field_tagaccept オプションを追加することで画像のみが選択可能となるようにしています。

Controller

Controllerはこんな感じ。

images_controller.rb
def upload_image
  source = params[:file]
  notice = "画像を選択してください。"

  if source
    file_name = source.original_filename

    s3 = Aws::S3::Resource.new(region: "ap-northeast-1")
    obj = s3.bucket("my_bucket").object("images/#{file_name}")

    obj.put({
      body: source.read,
      content_type: 'image/jpeg'
    })

    notice = "#{file_name}を保存しました。"
  end

  redirect_to images_path, :notice => notice
end

Aws::S3::Objectの put メソッドを使用してS3に画像をアップロードしています。
また、 redirect_tonotice オプションを追加することで画像アップロードの成否を通知しています。

ちなみに、 params[:file] で取得したオブジェクトは以下の感じでパラメータが取得できます。

  • ファイル名を取得: params[:file].original_filename
  • コンテンツタイプの取得: params[:file].content_type
  • ファイルサイズの取得: params[:file].size
  • ファイル本体の取得: params[:file].read

参考URL等

本記事の執筆にあたり参考にした順に並べています。

1
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
3