はじめに
フロントからファイルを受け取ってからS3アップロードするのは流石にサーバーの負担が大きい。
Presigned URLを利用して、直接クライアント側からS3にPutしよう!
実際は簡単ですが、途中のConfigに少々問題があったので、一応メモを残そうと。
実装
mix.exs
defp deps do
[
{:phoenix, "~> 1.4.0"},
{:phoenix_pubsub, "~> 1.1"},
{:phoenix_ecto, "~> 4.0"},
{:ecto_sql, "~> 3.0"},
{:postgrex, ">= 0.0.0"},
{:phoenix_html, "~> 2.11"},
{:phoenix_live_reload, "~> 1.2", only: :dev},
{:gettext, "~> 0.11"},
{:jason, "~> 1.0"},
{:phauxth, "~> 2.0.0"},
{:argon2_elixir, "~> 1.3"},
{:bamboo, "~> 1.1"},
{:bamboo_ses, ">= 0.1.0"},
{:plug_cowboy, "~> 2.0"},
{:httpoison, "~> 1.5"},
##
{:ex_aws, "~> 2.1"},
{:ex_aws_s3, "~> 2.0"},
##
]
end
mix deps.get
config.exs
ここで少々時間をかかってしまった。
同じプロジェクトでsesも使ってるが、Regionが違う。
もしそのまま使うと下記のエラーが返される。
<?xml version="1.0" encoding="UTF-8"?>
<Error>
<Code>PermanentRedirect</Code>
<Message>The bucket you are attempting to access must be addressed using the specified endpoint. Please send all future requests to this endpoint.</Message>
<Endpoint>authpractice.s3.amazonaws.com</Endpoint>
<Bucket>authpractice</Bucket>
<RequestId>485F22E3265A08E1</RequestId>
<HostId>vmSaFTUKuz9azNZkjOcevjn7II5cPsZivRlz6QRf8pgfT2jIf50f4etFfgUVULBnL4GbltWTZdk=</HostId>
</Error>
なので、このようにConfigを分けると、後でサービスごとのConfigをロードできるようなのでこのように書けよう。
config :ex_aws,
access_key_id: System.get_env("AuthIAMUserAccessKey"),
secret_access_key: System.get_env("AuthIAMUserSecretAccessKey")
config :ex_aws, :s3,
region: "ap-northeast-1",
host: "s3.ap-northeast-1.amazonaws.com"
実際にPresigned URLを生成するコード:
# ここでConfigをロードする
ExAws.Config.new(:s3)
|> S3.presigned_url(
:put,
"bucketname",
"filename"
)