12
5

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 3 years have passed since last update.

ファイルアップロード時のRailsにおけるmultipart指定について

Last updated at Posted at 2021-05-13

この記事について

ユーザーのアバター画像を設定するためにCarrierwaveを使って画像のアップロード機能を実装していたところ、なぜか画像がアップロードされないエラーが発生した。Railsにおけるmultipart指定について理解が曖昧だったのが原因だったこともあり、その時の対応策を備忘録として残しておきます。

環境

Rails6 (6.1.3)
Carrierwave(2.2.1)

エラー内容

画像ファイルを選択した上でsubmitしても画像が登録されなかった。
パラメータを確認したところ以下のようにavatarのパラメータ値がファイル名になっている。

Parameters: {"authenticity_token"=>"[FILTERED]",
 "user_profile"=>{
  "name"=>”~~~~~~”, 
  "avatar"=> “avatar-img.jpg"
}, "commit"=>"更新", "id"=>"1"}

本来は以下のようにActionDispatch::Http::UploadedFileによってファイル名や画像の形式などが 渡されなければならないはず。

Parameters: {"authenticity_token"=>"[FILTERED]",
"user_profile"=>{
 "name"=>”~~~~~~”, 
 "avatar"=>#<ActionDispatch::Http::UploadedFile:0x00007f66d8e0cae0 
 @tempfile=# <Tempfile:/tmp/RackMultipart20210420-9-18sadv85o.jpg>,
 @original_filename=“avatar-img.jpg",
 @content_type="image/jpeg",
 @headers="Content-Disposition: form-data; name=\"user_profile[avatar]\"; filename=\"avatar-img.jpg\"\r\nContent-Type: image/jpeg\r\n">
},
"commit"=>"更新", "id"=>"1"}

設定ファイル関連で何かエラーがあるのかと,carrierwave.rbuploader.rbなどを確認したが問題はなさそう。
ファイル名がそのまま渡されていたのをヒントにmultipartの指定が怪しいと思い:multipart => true をformタグに追加してみると無事にファイルアップロードできた!

= form_with model: @user_profile, url: user_profile_path(@user_profile), html: { method: :patch, multipart: true } do |f|

multipartとは

multipartは複数の種類のデータを一度に扱える形式で、trueを指定することでフォームで文字列だけでなくcsvファイルや画像データなどを扱うことができる。今回はこの指定がされていなかったのでファイルを読み込んでもファイル名が文字列と認識されてしまい、
画像ファイルをアップロードする事が出来ていなかった。

:multipart => trueは必ず指定しないといけない?

しかし、Railsで過去にファイルのアップロードを含むフォームを実装した際には:multipart => trueを指定しなくてもうまく機能していた。

何故なのか不思議だったが、その答えはRailsガイドに記載されていた。

Action View Form Helpers 6 Uploading Files

どうやら form_withメソッドでモデルを指定したフォーム内にfile_field使用すると、自動的に:multipart => trueが適用されるらしい。

<%= form_with model: @person do |f| %>
  <%= f.file_field :picture %>
<% end %>

モデルを指定しない場合は:multipart => trueを指定しないといけない

<%= form_with url: "/uploads", multipart: true do |f| %>
  <%= f.file_field :picture %>
<% end %>

今回はform_withメソッドでモデルを指定したフォームを使用していたが、アップロード画像のプレビュー表示をReactを使って実装していたため、file_fieldを使用していなかった。

.field
  = f.label :avatar
  = react_component("UserAvatarPreview")

そのため、ファイルアップロードのためには:multipart => trueを指定しないといけなかったらしい。

まとめ

  • form_withメソッドでモデルを指定したフォーム内にfile_field使用すると、自動的に:multipart => trueが適用される
  • モデルを指定していなかったりfile_field使用していない場合は:multipart => trueを指定しなければならない
12
5
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
12
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?