I have an application in Phoenix 1.6.2 that uploads files to Amazon S3 using ex_aws_s3.
On localhost the upload works fine for the bucket, but in production the upload doesn’t work.
This error happens:
15:49:33.135 [warn] ExAws: HTTP ERROR: :nxdomain for URL: "https:/prd-envixo-bucket.s3.amazonaws.com/1/logo/original-549bac34-7c85-42e6-b2cd-cb3ce7f71fab.png" ATTEMPT: 10
15:49:33.136 [error] GenServer #PID<0.2635.0> terminating
** (ExAws.Error) ExAws Request Error!
{:error, :nxdomain}
(ex_aws 2.2.9) lib/ex_aws.ex:87: ExAws.request!/2
(my_app 0.1.0) lib/my_app_web/live/register_wizard/register_wizard_step2_live.ex:87: anonymous fn/4 in MyAppWeb.RegisterWizardStep2Live.consume_logo/2
(phoenix_live_view 0.17.2) lib/phoenix_live_view/upload_channel.ex:20: Phoenix.LiveView.UploadChannel.consume/3
I’ve tried several different settings, but nothing works.
Looks like the ex_aws_s3 has a bug and generates the wrong URL.
My prod.secret.exs file:
config :ex_aws,
bucket: System.fetch_env!("AWS_BUCKET"),
cloud_front: System.fetch_env!("AWS_CLOUD_FRONT"),
region: System.fetch_env!("AWS_REGION"),
access_key_id: [System.fetch_env!("AWS_ACCESS_KEY_ID"), :instance_role],
secret_access_key: [System.fetch_env!("AWS_SECRET_ACCESS_KEY"), :instance_role]
config :ex_aws, :s3, scheme: "https://"
And this is my code that uploads the file:
@s3_bucket Application.fetch_env!(:ex_aws, :bucket)
defp s3_url, do: "#{@s3_bucket}.s3.amazonaws.com"
def consume_logo(socket, current_enterprise) do
consume_uploaded_entries(socket, :logo, fn meta, entry ->
# Delete old file if exists on S3
if current_enterprise.logo_original_url do
logo_path = file_s3_path(current_enterprise.logo_original_url)
ExAws.S3.delete_object(s3_url(), logo_path) |> ExAws.request!()
end
if current_enterprise.logo_thumbnail_url do
logo_path = file_s3_path(current_enterprise.logo_thumbnail_url)
ExAws.S3.delete_object(s3_url(), logo_path) |> ExAws.request!()
end
# Upload new original file to S3
original_url = Path.join(s3_url(), filename(entry, socket, :original))
{:ok, original_contents} = File.read(meta.path)
ExAws.S3.put_object(s3_url(), file_s3_path(original_url), original_contents) |> ExAws.request!()
# Resize and upload thumbnail file to S3
thumbnail_url = Path.join(s3_url(), filename(entry, socket, :thumbnail))
thumbnail = Image.resize(meta.path, 189, 50)
{:ok, thumbnail_contents} = File.read(thumbnail.path)
ExAws.S3.put_object(s3_url(), file_s3_path(thumbnail_url), thumbnail_contents) |> ExAws.request!()
# Delete temp files
File.rm!(meta.path)
File.rm!(thumbnail.path)
# Return a new url image for original and thumbnail
{original_url, thumbnail_url}
end)
end
defp file_s3_path(file_url) do
file_url |> String.replace("#{s3_url()}/", "")
end
defp filename(entry, socket, type) do
[ext | _] = MIME.extensions(entry.client_type)
"#{socket.assigns.current_enterprise.id}/logo/#{type}-#{entry.uuid}.#{ext}"
end
Does anyone know how I can solve this problem?
Thank you for your help.