経緯
PaperclipにURLで画像を登録したら、一部の画像がContent typeのvalidationで弾かれた。
Railsは4.2.6、Paperclipは4.3.6でした。
エラーメッセージ
[paperclip] Content Type Spoof: Filename 1467013624.jpg
(application/octet-stream from Headers, ["image/jpeg"] from Extension),
content type discovered from file command: image/jpeg.
See documentation to allow this combination.
レスポンスヘッダはapplication/octet-streamだけど拡張子から推測するにimage/jpegだよね?変でしょ?直して!ってことらしい。
issueになってた
Content Type Spoofのエラーを出さない方法は、
config/initializer/paperclip.rbに
require 'paperclip/media_type_spoof_detector'
module Paperclip
class MediaTypeSpoofDetector
def spoofed?
false
end
end
end
こう書くらしい。
確かにエラーは出なくなった。
でもまだvalidationで弾かれる。
原因
こんなふうに書いてた
data = Paperclip.io_adapters.for(url)
data.original_filename = url
Image.new(image: data)
ここで
puts data.content_type
すると、
application/octet-stream
って返ってくる。
image/*じゃないからダメだったらしい。
じゃあこのエラーメッセージはどうやってimage/*のcontent typeをゲットしてるんだろうとエラー元を見てみた。
そしたらファイル名からcontent typeを教えてくれるのを見つけた。
https://github.com/thoughtbot/paperclip/blob/e60f00027704298455c039e111d96bcf46e12822/lib/paperclip/media_type_spoof_detector.rb#L57
というわけで
data = Paperclip.io_adapters.for(url)
data.original_filename = url
data.content_type = MIME::Types.type_for(url).first.content_type
return Image.new(image: data)
こうなった。
MIME::Types.type_for(url)はArrayで返ってくるみたいだから最初を取り出した。
めでたし。