phoenixからs3に画像をアップロードする

Elixir Phoenix Web
更新2020/12/01
画像をアップロードしてs3に保存するときに必要なことをまとめておきます。

前段

ex_awsを使う感じのようです。
ほとんどこのドキュメントの通りなんですが、ちょっとハマったり、???となったところもあったのでまとめておきます。

大まかな流れ

概要

ex_awsパッケージ自体はs3を扱う部分などが分離されているみたいでdepsには下記のように書くようだ。(readmeより)
defp deps do
  [
    {:ex_aws, "~> 2.1"},
    {:ex_aws_s3, "~> 2.0"},
    {:hackney, "~> 1.9"},
    {:sweet_xml, "~> 0.6"},
  ]
end
作成したs3にPutObjectできるIAMロールを作成し、EC2等にアタッチ。ないしは、そのロールを持ったユーザーを作成してAWS_ACCESS_KEY_IDとAWS_SECRET_ACCESS_KEYを環境変数としてphoenixに渡せるようにする。
dev.exsやprod.exsに下記のように記述を追加することで、ロールの権限を使えるようになるようだ。

AWSのコンソールからIAMロールを付与した場合はaccess_key_idやsecret_access_keyをserverに置く必要はないが下記の記述は必要。

config :ex_aws,
       region: "ap-northeast-1", #お使いのリージョン
       access_key_id: [{:system, "AWS_ACCESS_KEY_ID"}, :instance_role],
       secret_access_key: [{:system, "AWS_SECRET_ACCESS_KEY"}, :instance_role]
フロントエンドから画像を含むparamを受け取る部分で下記にようにしてアップロード

upload = param["file"] # 
epoch_time = Timex.to_unix(Timex.now) # uploadする画像の名前につかうunixtimeを取得
extension = Path.extname(upload.filename) # uplaodする画像の拡張子を取得
filename = "#{epoch_time}#{extension}"
s3_path = "/upload/article/#{filename}"
{:ok, image_binary} = File.read(upload.path)
ExAws.S3.put_object("バケット名", s3_path, image_binary) |> ExAws.request! # s3にアップロード 

余談

ExAws.S3のドキュメントにはS3.put_objectと書いてあるのでそう書けるような気がしてしまうが、ExAws.S3.put_objectという形で呼ばないモジュールが見つからない。
書いた人/このブログについて

サーバーサイドエンジニア。お仕事ではRubyとPerl。趣味ではC#やHLSLなどを少しと、3DCGでPythonをごまかしながら使う感じ。Unityとインフラ周りも好き。

自分の備忘録もGoogle検索に任せたくてこのブログ書いてる。Phoenix製でEC2上で稼働中。