Ruby on RailsでPDFファイルを非同期でアップロードする方法を紹介します。PDFファイルを選択または変更した場合にファイル情報が非同期でサーバにアップロードされ、その情報を再度フロントに返すイメージです。
carriwaveを使ってPDFファイルカラムが存在するモデルと紐づけ
Gemのcarriwaveを使ってファイルをアップロードするため、インストールや設定をしておく必要があります(今回は省略)。
ファイルパスを保存するカラム(今回の場合はfile_name)を指定してモデルと紐づけます。
1 2 3 4 5 6 7 8 9 10 | class Hoge < ApplicationRecord ... # pdfアップローダー mount_uploader :pdf, FileUploader, mount_on: :file_name .... end |
PDFファイルアップロード処理(フロントエンド)
ViewでPDFファイrを選択するHTMLを生成します。
PDFファイルが選択された場合、または変更された場合に「Application.hoges.pdf_upload($(this))」イベントが発火します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <%= form_for @hoge, url: { action: action, id: @hoge.id }, html: { multipart: true }, remote: true, data: { method: :confirm } do |f| %> ... <div> <%= f.hidden_field :id %> <%= f.label :pdf do %> PDFファイル選択 <%= f.file_field :pdf, accept: ".pdf", url: "#{upload_tempfile_hoges_path}", onchange: "Application.hoges.pdf_upload($(this))" %> <%= f.hidden_field :file_name, id: "file_name" %> <%= f.hidden_field :pdf_cache, id: "cache_name" %> <% end %> <a class="pdf_file_name_label"><%= f.object.file_name || "選択されていません" %></a> </div> ... <% end %> |
CoffeeScriptで非同期のアップロード処理を書いていきます。
読み込んだPDFファイルの情報をFormDataに格納し、urlのパスにデータを送ります。
PDFアップロードに成功した場合は、その情報をViewに書き換えます。失敗した場合は、エラーモーダル(処理は省略)を表示させます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | class HogessController index: -> @pdf_upload = (input) -> file_uploader(input) # PDFアップロード file_uploader = (input) -> file = input.prop('files')[0] formData = new FormData() formData.append("file", file) formData.append("filename", file.name) formData.append("name", input.parent().siblings('#file_link').find("label").attr("for")) $.ajax url: input.attr('url'), method: 'post', dataType: 'json', data: formData, processData: false, contentType: false .done (res) -> input.siblings('#cache_name').val(res.cache) input.siblings('#file_name').val(file.name) input.parents('.image_file-selection').find('.pdf_file_name_label').text(file.name).attr('href', res.pdf_url).attr('target', '_blank') return .fail (xhr, status, error) -> Application.show_error_modal(xhr) return return this.Application.hoges = new HogesController |
PDFファイルアップロード処理(サーバサイド)
発火したイベントによってPDFファイルデータが非同期でサーバに送られます。サーバに送るためにroutes.rbrbにルーティングを追加しておきます。
送られたデータを先ほど紐づけたモデルからアップロードします。アップロードしたデータの返り値を@fileに格納します。
1 | post :upload_tempfile |
1 2 3 4 5 6 7 8 9 10 11 12 | class Hoge < ApplicationRecord ... # PDFファイルアップロード def upload_tempfile @file = ::Hoge.new(pdf: params[:file], file_name: params[:filename]) end ... end |
@fileのデータをJSON形式で変数に格納し、アップロード結果をViewに表示します。
今回の場合は、画面でアップロードしたファイルを確認できるようにするためファイルパスを返しています。
また、DBに登録や更新処理をする際のパラメータとして、アップロードしたキャッシュデータをinputタグに埋め込んでいます。
・upload_tempfile.js.erb
1 2 3 4 5 | upload_tempfile.js.erb { "pdf_url": "<%= @file.pdf.url %>", "cache": "<%= @file.pdf.cache_name %>" } |
以上、Railsで非同期にPDFファイルをアップロードする方法でした。