ローカル環境ではEXIFデータを取り出せていたのに、S3に切り替えたら画像のEXIFデータを取り出せず詰まってしまいました。
悩み 調べ 書き切れないほどに試して解決できました。同じ様な症状に陥った方のデバッグのヒントになるかもしれないのでまとめていきます。
前提:
・EXIFデータを取得するためにexifr
を使用しています。
1. 状況によって取り出し方が違う
① 既にS3へアップロードされているEXIFデータを取り出したい場合
結論:
S3に保存した画像からはEXIFデータの取得は基本的にできないようです。
取り出すために行うこと:
画像ファイルをS3からlocalに一時的にダウンロードして、落とした画像からメタデータを取り出す必要があります。
※今回はこちらの説明は含んでおりません。(今後、個人的に実装した場合に追加していきます)
② S3へ画像をアップロードする際にEXIFデータを取り出したい場合
アップローダの記述を以下でいけます:
ポイントは①です!
class ImageUploader < CarrierWave::Uploader::Base
attr_accessor :latitude, :longitude, :datetime *** ① ***
if Rails.env.production?
storage :fog
else
storage :file
end
process :get_exif_info
def get_exif_info *** ② ***
begin *** ③ ***
require 'exifr/jpeg'
exif = EXIFR::JPEG::new(self.file.file)
@latitude = exif.gps.latitude
@longitude = exif.gps.longitude
@datetime = exif.date_time
rescue
end
end
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
end
解説:
①attr_accessor
を使ってインスタンス変数を渡しています。
②緯度・経度・撮影日のデータを格納。
③begin - rescueを使って例外処理をしています。
EXIFデータの有無で処理を分けているので、データがない場合の処理を書きたい場合は、rescue
とend
の間に書く。
あとはアクション内で以下みたいにすれば取得できます!
僕の場合はここでデータベースに保存させました。
@post.latitude = @post.image.latitude
@post.datetime = @post.image.datetime
今となってはこれだけだったんですが、paramsで取得することに執着して完全に見失っておりました。
ここで渡してあげないと、アップローダで取得したデータ値をアクション内で使えません(nilになります)
アクション内でデータ値を使う為に他に試したこと:
1.そもそもアップロード時に取得できているのか?
get_exif_infoメソッド内での実行結果:
EXIFR::JPEG::new(self.file.file).gps.latitude
=> 35.29805555555556
EXIFR::JPEG::new(self.file.file).date_time
=> 2020-10-03 08:18:00 +0900
取得はできている。
ちなみにS3側にも画像は保存されている。
2. instance_variable_get
で強引に取ってきてみる
obj = ImageUploader.new
binding.pry
obj.instance_variable_get("@latitude")を実行してみる
実行結果:➡︎ nil
3. パスを指定して取得してみる
S3には間違いなくアップロードされているので、
オブジェクト URL をダイレクトに指定してみる。
EXIFR::JPEG::new("オブジェクト URL/#{@post.fish_image.path}")
実行結果:
Errno::ENOENT: No such file or directory @ rb_sysopen
S3 URIをダイレクトに指定してみる。
EXIFR::JPEG::new("S3 URI/#{@post.fish_image.path}")
実行結果:
Errno::ENOENT: No such file or directory @ rb_sysopen
まとめ
結局はシンプルにアクセサーで渡してしまうのが手っ取り早いようです。
そのあとで、データベースに保存させれば活用できました。