0
1

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.

AWS S3に画像をアップロードする際にEXIFデータを取り出す方法

Posted at

ローカル環境ではEXIFデータを取り出せていたのに、S3に切り替えたら画像のEXIFデータを取り出せず詰まってしまいました。
悩み 調べ 書き切れないほどに試して解決できました。同じ様な症状に陥った方のデバッグのヒントになるかもしれないのでまとめていきます。

前提:
・EXIFデータを取得するためにexifrを使用しています。

1. 状況によって取り出し方が違う

① 既にS3へアップロードされているEXIFデータを取り出したい場合

結論:
S3に保存した画像からはEXIFデータの取得は基本的にできないようです。

取り出すために行うこと:
画像ファイルをS3からlocalに一時的にダウンロードして、落とした画像からメタデータを取り出す必要があります。
※今回はこちらの説明は含んでおりません。(今後、個人的に実装した場合に追加していきます)

② S3へ画像をアップロードする際にEXIFデータを取り出したい場合

アップローダの記述を以下でいけます:
ポイントは①です!

image_uploader.rb

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データの有無で処理を分けているので、データがない場合の処理を書きたい場合は、rescueendの間に書く。

あとはアクション内で以下みたいにすれば取得できます!
僕の場合はここでデータベースに保存させました。

@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

まとめ

結局はシンプルにアクセサーで渡してしまうのが手っ取り早いようです。
そのあとで、データベースに保存させれば活用できました。

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?