AWS S3 File uploading using presigned url


I am trying to generate a presigned url which I can send to a react frontend. However I am struggling to generate a presigned url with ex_aws_s3.


{:ex_aws, "~> 2.1.2"},
{:ex_aws_s3, "~> 2.0"},
{:hackney, "~> 1.9"},
{:sweet_xml, "~> 0.6"}


source .env
iex -S mix phx.server

IEX code

bucket = "fls-bm-app"
path = "/place_image/"

query_params = [{"ContentType", "image/png"}, {"ACL", "public-read"}]
presign_options = [virtual_host: true, query_params: query_params]
|> ExAws.S3.presigned_url(:put, bucket, path, presign_options)

This returns a the following url

When trying to push a file from the frontend to the above url it creates the folder /place_image/ only, but it doesn’t upload the file.

I am stumped as to where to go from here.

Sounds like you are trying to push the file vs downloading it? I could be wrong, but I though presigned_url was only for getting a download link, maybe you need to use presigned_post?

For uploading files I’ve used put_object, i.e.

      local_file =!(src_path)

      ExAws.S3.put_object(@bucket, dest_path, local_file)
      |> ExAws.request!()

I don’t know if that will be of us to you however, given you are using react on the frontend.

1 Like

Try putting the full file name in this path. So something like “/place_image/myfile.jpg”

Although I would recommend presigned post as well because then you can avoid a CORS preflight request.

1 Like

Thank you @riebeekn for the suggestion, this is exactly what I was looking for.

I created a video going more into detail about the implementation and usage of it.

Related article: Demystifying direct uploads from the browser to Amazon S3 - with a full example in 167 lines of code - Leonid Shevtsov

1 Like