1
0

More than 1 year has passed since last update.

Carrierwaveでヘッダー指定のURLから画像を取得して保存する

Last updated at Posted at 2022-02-07

概要

Carrierwaveを使用して外部サイトもしくはS3などから画像をダウンロードして保存する。
その際にヘッダーを指定する(今回はRefererのみ)
carrierwave側では画像のcontent_typeをpng/jpg/jpegに限定している。

試したけどうまくいかなかったパターン

open-uriでopenした画像を保存する

image_uri = URI.parse(uri) # uriを直接openするとセキュリティ的に問題があるためURI.parseする
file = image_uri.open("Referer" => "https://...")
user.avater = file

値が入らず断念。tmpファイルに書き出してから行えばうまくいけるかも。

2022年6月15日加筆

参考URL: https://docs.ruby-lang.org/ja/latest/library/open=2duri.html
値が入らなかったのはCarrierWaveがcontent_typeを拡張子から判断していたため。
open_uriで開いたファイルはTempfileクラスとして開かれるが、拡張子の命名規則がデフォルトではcontent_typeから類推してくれないことにより
バリデーションエラーが出てしまっていた。
保存するためにはダウンロードしたファイルのファイル名に.jpgなどの拡張子をつける必要があるので今回はCarrierWave::SanitizedFileクラスを利用する。
詳細に関してはこちらを参照ください。
https://github.com/carrierwaveuploader/carrierwave/blob/54f0ef9b1da48f9651f4428e78d19765ab7d3df2/lib/carrierwave/sanitized_file.rb

image_uri = URI.parse(uri) # uriを直接openするとセキュリティ的に問題があるためURI.parseする
res = OpenURI.open_uri(image_url, "Referer" => "https://...")
file = CarrierWave::SanitizedFile.new(tempfile: res, filename: res.base_uri.to_s, content_type: res.content_type)
user.avater = file

上手く行ったパターン

carrierwaveのremote_#{column}request_header=(header)とremote#{column}_url=(url)を使用する

carrierwaveのソースを読むと以下のようなメソッドが定義されているので利用する
columnの部分はモデルのmount_uploaderで指定したカラム名を使用する
今回はavaterカラムを例に使用
https://github.com/carrierwaveuploader/carrierwave/blob/229594fb2ac7cfa59586162c0b3fc3d0b5bab978/lib/carrierwave/mount.rb#L165

image_url = URI.parse(uri).to_s # URIクラスだと受け付けない
user.remote_avater_request_header = {"Referer" => "https://..."}
user.remote_avater_url = image_url
user.save!

1
0
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
1
0