Paperclipでコンテンツタイプが合っているのにspoofed_media_typeエラーでアップロードできない

TECH
2017.06.15
Pocket

Paperclipでコンテンツタイプが合っているのにspoofed_media_typeエラーでアップロードできない

Ruby on Railsで画像などのファイルをアップロードし、保存するための有名なGemにPaperclipがあります。
このGemではModelにファイルに対してバリデーションをかけることができます。詳しくは公式ページでご確認ください。

2017年6月時点の最新版であるVersion 5.1.0ではアップロード可能なコンテンツタイプ(ファイルタイプ)を指定しなければいけません。
例えばこのようにするとJPG画像のみアップロードが可能になります。

validates_attachment :avatar, content_type: { content_type: "image/jpeg" }

もし、JPG以外の画像をアップロードしようとするとエラーが出ます。

Command :: file -b --mime '/tmp/image.png'
[paperclip] Content Type Spoof: Filename image.png (image/png from Headers, ["image/png"] from Extension), content type discovered from file command: image/png See documentation to allow this combination.

PNG画像のアップロードが許可されていないのにアップロードをしてしまったため、バリデーションで弾かれてしまっています。

通常は上記のように許可されたコンテンツタイプ以外のファイルをアップロードしようとするとエラーが出ます。
しかし、コンテンツタイプが合っているのに同様のエラーが出る場合があります。
以下のような感じです。

Command :: file -b --mime '/tmp/image.jpg'
[paperclip] Content Type Spoof: Filename 500.jpg (image/jpeg from Headers, ["image/jpeg"] from Extension), content type discovered from file command: . See documentation to allow this combination.

このメッセージから気になる点が2つあります。
まずは2行目のファイルネームがアップロードした「image.jpg」ではなく「500.jpg」になっています。
そしてfileコマンドで見つかったコンテンツタイプが「.」となっています。

実はこれはfileコマンドがないために起きるエラーです。
Paperclipではfileコマンドでアップロードされたファイルのコンテンツタイプを判別しています。
しかし、fileコマンドが入っていない場合、エラーが返ってきます。つまりアップロードしたファイル自体には問題がなくても、その判別の時点でエラーになってしまうため、Paperclipのバリデーションをクリアしなくなってしまうんです。

このエラーを回避するためにはfileコマンドをインストールすれば大丈夫です。
以下のいずれかのコマンドでfileコマンドをインストールしてください。

sudo yum install file
ssudo apt-get install file

fileコマンドが使えるようになればファイルのアップロードが成功すると思います。

Pocket