レイルズで複数の添付ファイルを1画面でアップロードする
rails(4.2.1), jquery-fileupload-rails (0.4.5)
jQuery-File-Uploadを使う。
https://github.com/blueimp/jQuery-File-Upload/wiki/Basic-plugin
1投稿に対して複数の添付ファイルをつける画面作る。
$ -> $('#fileupload').fileupload url: '/post_attachments.json' add: (e, data) -> $div = $("<div name='#{data.files[0].name}'>#{data.files[0].name}</div>") $("#filelist").append($div) data.context = $div if data.files[0].size > 10000000 $div.text($div.text() + "[サイズオーバー]") $div.css({ color: 'red' }) else data.submit() done: (e, data) -> $.each data.response().result, (_, item) -> $('#fileupload').append( $("<input type=hidden name=temp_post_attachment_ids[] value=#{item['post_attachment_id']}>") ) data.context.text(data.context.text() + "[ok]") data.context.css({ color: 'green' })
class PostAttachmentsController < ApplicationController def create attachments = params.permit(attachment: [])[:attachment].map do |f| x = PostAttachment.create(attachment: f.tempfile) { post_attachment_id: x.id, attachment_file_name: x.attachment_file_name, original_filename: f.original_filename } end render json: attachments end end
addコールバックでは、サーバに送信される前の状態なので、ここでサイズチェックできるの便利。
data.contextプロパティにエレメントを代入しておくと、アップロードが完了した時も同じファイルのcontextプロパティを参照できるのでテキストの更新が楽にできる。便利。
addコールバックの後は、PostAttachmentsController#createがリクエストを受け取る。
ファイルの保存が成功すると、doneコールバックはが発火する。この中ではformタグ内にhiddenタグをどこどこ追加してる。
ちなみにdata.submit() されたファイルだけdoneコールバックが呼ばれる。これも便利。
= form_for @post, html: { multipart: true, class: :post_form, id: :fileupload } do |f| .form-group = file_field_tag "attachment[]", multiple: true #filelist.well.alert.alert-notice = f.submit class: 'btn btn-primary'
file_field_tagヘルパー でファイル選択のダイアログを出して、選択されたファイルは、jQuery-File-Uploadが横取りするので`同期通信`ではこのinputタグには値は設定されない。
class PostsController < ApplicationController ... def create @post = Post.new(post_param) if @post.save PostAttachment.where( id: params[:temp_post_attachment_ids], post_id: nil ).update_all(post_id: @post.id) else ... end end
一時的にアップロードしているのでテーブルの定期的な掃除は必要そう。
これでドラック & ドロップでのアップロードもできるし複数アップロードも対応してる。便利。