概要
Dropzone.js という JavaScript ライブラリがクールだったので、これを Rails アプリケーションで利用する方法をご紹介します。
Dropzone.js について
ドラッグ & ドロップによるファイルアップロード機能を提供する JavaScript ライブラリです。通信は Ajax で行われます。
この形式は PC 向けの Web アプリケーションでは結構見かけると思います。この Qiita でも使われていますね。
Dropzone.js 見た目は以下のとおりです。なお、デフォルトでは外枠は実線ですが、公式サイトのデモに合わせて CSS で破線にしています。
ここにファイルをドラッグ & ドロップするとこのようになります。プレビューとして、画像ファイルはサムネイルが表示され、ドキュメントファイルはファイルサイズやファイル名などの情報が表示されます。
また、画像ファイルにマウスカーソルをホバーすると、ドキュメントファイルと同様にファイル情報が表示されます。
おしゃれですね
ちなみに、ファイルは複数同時にドラッグ & ドロップすることが可能です。
導入
では実際に Rails アプリケーションに導入したいと思います。
dropzonejs-rails という Gem が公開されているので、まずはそれをインストールします。
# 2016/03/09 時点での最新バージョンは 0.7.3 です。
gem 'dropzonejs-rails', '~> 0.7.3'
$ bundle install
そして application.js
と application.css
に以下を追記します。
//= require dropzone
*= require dropzone/basic
*= require dropzone/dropzone
次に View を実装します。まず例として、僕の Rails アプリケーションでは、ファイルアップロードのために以下のような Model と Controller を実装済みと仮定します。特定の書類 (Document) に対して添付ファイル (Attachment) を作成するイメージです。
class Document < ActiveRecord::Base
has_many :attachments, dependent: :destroy
end
class Attachment < ActiveRecord::Base
belongs_to :document
# この例ではサーバサイドでのファイルアップロードに Paperclip という Gem を利用している想定です。
# ただこの記事はサーバサイドでのファイルアップロード方法には関係しないので、
# お好きな Gem をご利用ください。
has_attached_file :file
end
class AttachmentsController < ApplicationController
def create
@attachment = Attachment.create!(create_params)
end
private
def create_params
params.require(:attachment).permit(:document_id, :file)
end
end
Dropzone.js 用の View は form_tag を使って以下のように実装します。
<%= form_tag(attachments_path, class: 'dropzone', id: 'upload-dropzone') do %>
<div class="fallback">
<%= file_field_tag('attachment[file]') %>
</div>
<% end %>
なお、file_field_tag の第 1 引数、つまり input 要素の name 属性は JavaScript 側で明示する必要があります。さもないと attachment[file]
が file
になってしまいます。そのため、実際は file_field_tag
の引数は任意の値で構いません。
次にクライアントサイドを実装します。
Dropzone.autoDiscover = false
new Dropzone '#upload-dropzone',
uploadMultiple: false
paramName: 'attachment[file]'
params:
'attachment[document_id]': 123
init: ->
@on 'success', (file, json) ->
# アップロード成功時の処理をここに実装します。
dictDefaultMessage: '''
<i class="fa fa-file-o fa-2x"></i><br>
<br>
ファイルをここにドロップするか<br>
ここをクリックして下さい
'''
パラメータを { attachment: { file: ... }
という具合にネストさせたいので paramName
を指定します。また、他にもパラメータを渡す必要がある場合は params
オプションで指定します。ちなみに、この params
オプションは 公式サイトの説明 に載っておらず、GitHub の Issue で知りました。
最後に CSS で見た目を調整します。最初に述べたとおり、僕はボーダーを破線にしたり角を丸くしたりしています。また、Dropzone の中に表示される文言の表示も調整しています。
@import 'compass/css3/border-radius';
.dropzone {
border: 2px dashed #b4bcc2;
@include border-radius(4px);
.dz-message {
font-size: 16px;
text-align: center;
margin: 0
}
}
以上で実装は完了です。
おまけ
プレビューを非表示にする
プレビューを表示したくない場合はこのようにします。
Dropzone.autoDiscover = false
new Dropzone '#upload-dropzone',
uploadMultiple: false
paramName: 'attachment[file]'
params:
'attachment[document_id]': 123
init: ->
@on 'success', (file, json) ->
# アップロード成功時の処理をここに実装します。
dictDefaultMessage: '''
<i class="fa fa-file-o fa-2x"></i><br>
<br>
ファイルをここにドロップするか<br>
ここをクリックして下さい
'''
previewTemplate: '<div style="display:none"></div>' # このオプションを追加します。
// アップロード後も dictDefaultMessage の文言を表示したままにします。
.dropzone.dz-started .dz-message {
display: block;
}
参考
- 公式サイト
- Rails アプリケーションへの導入
- 追加パラメータを渡す方法
- プレビューを非表示にする方法