79
81

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Refileを使ってハイテクなアップローダ(機能を利用したサンプル)を作ってみたのでメモ

Last updated at Posted at 2015-07-07

Refile

昨日知ったのですが、Refileというファイルアップロード用のgemがとてもナウい感じです。

id:willnetさんとかが記事にしてました。

ざっと触ってみて、そのうち使えそうだったのでメモ。

作ったサンプル

Readmeほぼそのまま

基本

01.PNG

02.PNG

普通のアップロード機能を実装しました。

サムネイル表示忘れましたが、ヘルパが用意されています。

Sinatra製の画像サーバが内蔵されていて、そちらで"表示時の"リサイズ、クリッピング等に対応します。Rails利用時には自動的にマウントされるようです。

利用する場合はフロントキャッシュ等と組み合わせることが必須になりますが、とても便利ですね。見たところキャッシュ用のHTTPヘッダもきちんと使用されているようですので、リバースプロキシとしてnginxを使っているならとても簡単に設定できることでしょう。

あとはCloudFrontのカスタムオリジンあたりが簡単でしょう。

S3への保存

03.PNG

今回保存先をS3にしたのでそちらにアップロードされました。

Refile.store = Refile::S3.new(prefix: "store", **aws)

確認画面を実装してみる

公式の方法はわからなかったので、コードを読んで適当に実装しました。適当なのでこれではうまくいかないケースもあるかもです。

    <% if f.object.confirming? %>
        <div class="field">
            <%= f.label :name %><br>
            <%= f.object.name %>
            <%= f.hidden_field :name %>
        </div>

        <% if f.object.file.present? %>
            <div class="field">
                <%= f.hidden_field :file, value: f.object.file_attacher.data.to_json %>
                <%= image_tag attachment_url(f.object, :file, :fill, 200, 200) %>
            </div>
        <% end %>

file_attacherの所は現在のmasterではfile.attacherになるみたいです。

これで無事確認画面で画像のプレビューができました。

なお、レコードを保存する前、アップロードしただけの状態のファイルはcacheと呼ばれます。

Refile.cache = Refile::S3.new(prefix: "cache", **aws)
Refile.store = Refile::S3.new(prefix: "store", **aws)

今回、上記のようにして、実際の保存先及びcacheのどちらもS3に設定したので、cacheもS3上にあります。

04.PNG

これの何が嬉しいかというと、確認画面を実装した場合に、保存先がローカルストレージだと複数台のアプリサーバで構築しているシステムの場合に、確認画面と保存で別々のサーバに割り振られ、うまくいかなくなる可能性があります。

carrierwaveの場合、今日現在普通にインストールできるバージョン(0.10.0)ではこのようなケースでうまく行かないのですが、Refileの場合は現在バージョン(0.5.5)でも問題なくS3を利用した場合でも確認画面を実装できました。

ファイル削除に対応

05.PNG

Readmeの通りなのですが、先に実装した確認画面で、削除にチェックを入れた場合に表示したくなかったので、次のようにRefile::Attacher#remove?を使ってみました。例によってドキュメントにないので正しい方法かはわかりません。

    <% if f.object.confirming? %>
        <div class="field">
            <%= f.label :name %><br>
            <%= f.object.name %>
            <%= f.hidden_field :name %>
        </div>

        <% if f.object.file.present? %>
            <% unless f.object.file_attacher.remove? %>
                <div class="field">
                    <%= f.hidden_field :file, value: f.object.file_attacher.data.to_json %>
                    <%= image_tag attachment_url(f.object, :file, :fill, 200, 200) %>
                </div>
            <% end %>
        <% end  %>
        <%= f.hidden_field :remove_file %>

ダイレクトアップロード

ドキュメントまま。

RefileのJavaScriptライブラリを使うことで、ヘルパにdirect: trueオプションを追加するだけで、ファイルを選択されたら直接アップロードを開始できるようになります。ユーザーの待ち時間を減らすことができますね。

コントローラやモデルへの変更は一切不要です。

<%= f.attachment_field :file, direct: true %>

Presigned uploads(S3への署名付き URL を使用したオブジェクトのアップロード)

ヘルパにpresigned: trueオプションを追加するだけで、サーバを介さずに、ブラウザから直接S3へアップロードできるようになります。

それも、コントローラやモデルへの変更は一切不要、通常のアップロードと同じように扱えるのが素晴らしいです。

署名付き URL を使用したオブジェクトのアップロードについてはこちらを。

また、この機能は先のダイレクトアップロード機能と併用することもでき、

<%= f.attachment_field :file, direct: true, presigned: true %>

このようにすると、ファイルを選択した時点ですぐにS3に直接アップロードされます。

仕組みとしては、ビューのレンダリングの際に、S3の署名付きURLを発行してdata属性にセットしておき、onchangeハンドラで使用する、というもののようです。なるほど、勉強になります。

ファイル種類の検証

拡張子やMIMEタイプ、MIMEタイプのグループ(デフォルトで提供されるものほか、独自に定義可能)の制限が簡単にできます。

複数ファイルのアップロード

06.PNG

07.PNG

08.PNG

input type="file" multipleを使って複数選択したファイルを一括アップロードでき、それを一対多で保存できます。

この機能も、ダイレクトアップロード、署名付きURLでのアップロードにも対応しており、以下のようにして利用できます。

<%= f.attachment_field :images_files, multiple: true, direct: true, presigned: true %>

※2015.7.6現在の最新リリース(0.5.5)には含まれていないので、使いたいならgithubからインストールする。

gem 'refile', require: 'refile/rails', github: 'refile/refile'
79
81
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
79
81

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?