Elixir / Phoenix — Uploading images to AWS S3 (With ARC)

Hello, and thanks for checking in. In this post, I’d like to discuss how to upload images to an S3 bucket. We will continue working on the application we wrote earlier - Imageer. If you haven’t worked your way through it, I recommend doing so first. Elixir / Phoenix — Uploading images locally (With ARC)

Last time, we successfully managed to upload images to a local folder, and display the images in our images index template. Uploading to S3 with ARC requires us to install a couple of more packages:

# mix.exs
applications: [:phoenix, :phoenix_pubsub, :phoenix_html, :cowboy, :logger, :gettext,:phoenix_ecto, :postgrex, :arc_ecto, :ex_aws, :httpoison, :poison]]......defp deps do
[{:phoenix, “~> 1.2.1”},
{:phoenix_pubsub, “~> 1.0”},
{:phoenix_ecto, “~> 3.0”},
{:postgrex, “>= 0.0.0”},
{:phoenix_html, “~> 2.6”},
{:phoenix_live_reload, “~> 1.0”, only: :dev},
{:gettext, “~> 0.11”},
{:cowboy, “~> 1.0”},
{:arc, “~> 0.5.2”},
{:arc_ecto, “~> 0.4.4”},
{:ex_aws, “~> 0.5.0”}, #new package
{:poison, “~> 2.0”}, #new package
{:httpoison, “~> 0.9.0”}] #new package

We also added the new packages to our applications, so that they get run when we start our server.

Let’s install the new packages:

~/imageer$ mix deps.get
Running dependency resolution
Dependency resolution completed

We’ll restart our application, and everything should be up and running.

Now, we are going to configure ARC and ex_aws to work properly with S3. First create a new s3 bucket, and add the configurations to our dev.exs file (since we’re working on a dev environment)

config :arc,
bucket: “nameofyourbucket”,
virtual_host: true
config :ex_aws,
access_key_id: “accesskey”,
secret_access_key: “secretkey”,
region: “eu-central-1”,
host: “s3.eu-central-1.amazonaws.com”,
s3: [
scheme: “https://”,
host: “s3.eu-central-1.amazonaws.com”,
region: “eu-central-1”

If you are using the standard US bucket, you don’t need to set virtual_host, region, host or s3 configs. These are for using buckets other than the standard one. We also need to restart our server after the configurations.

Now, if we try and upload an image, it gets uploaded, however the image isn’t visible for us. If we look in our source code (HTML) we have:

<h4><a href=”/images/new”>Upload new image</a></h4> 
<img src=”https://yourbucket.s3.amazonaws.com/uploads/cat1.jpeg?v=63641413100"><br>
<img src=”https://yourbucket.s3.amazonaws.com/uploads/cat2.jpeg?v=63641413105"><br>
<img src=”https://yourbucket.s3.amazonaws.com/uploads/cat1.jpeg?v=63643235268"><br>

So the image path is properly set. However, if we click on any of the links, we’ll get a “Access Denied” error from AWS. We need to add a simple policy to our S3 bucket. We can do so by clicking on our newly created bucket in the AWS console, click Properties, Permissions and “Add bucket policy”. Copy and paste the following into it:

“Version”: “2012–10–17”,
“Id”: “Policy1380877762691”,
“Statement”: [
“Sid”: “Stmt1380877761162”,
“Effect”: “Allow”,
“Principal”: {
“AWS”: “*”
“Action”: “s3:GetObject”,
“Resource”: “arn:aws:s3:::yourbucketname/*”

This will allow a http get request to our bucket, so that our app can retrieve the images we just uploaded. If we try and refresh our website again, we’ll get cats!

Image for post
Image for post

The image between the cat pictures are from a previously uploaded image to our local folder, and is not available in our S3 bucket. let’s try and upload that image to our S3 (you can find it in the local upload folder):

Image for post
Image for post

Sweet! Our image upload to S3 works.

That’s it for now.
Until next time!
Stephan Bakkelund Valois

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store