File Upload using Elixir, Phoenix, Absinthe and ExAws

File Upload using Elixir, Phoenix, Absinthe and ExAws

Hello, I'm quite new in the elixir world. I want to write some notes so it will help me for later if I want to try this again. This guide will not really details. I will assume that you familiar enough to know about Elixir, Phoenix, Absinthe or ExAws itself. I will assume you are also familiar with AWS especially S3.

Alternative library that you might be interested:


  • Make sure you are already install Elixir in your computer/PC.
  • Generate new Phoenix Project. (If you are already have the Phoenix Project, you can skip this step).

mix archive.install hex phx_new

mix elixir_exploration


  1. Phoenix Installation Documentation
  2. Phoenix Generate Project
  3. Make sure you are already have PostgreSQL, if you not want to use database, please refer to note number 2, how to generate without Ecto which handle the database side.

  4. Add Absinthe and ExAWS as Dependencies. Add these to mix.exs

defp deps do
      ... # rest of dependencies, please not input this too
      {:absinthe, "~> 1.6"},
      {:absinthe_plug, "~> 1.5"},
      {:absinthe_phoenix, "~> 2.0"},
      {:ex_aws, "~> 2.2"},
      {:ex_aws_s3, "~> 2.0"},
      {:poison, "~> 3.0"},
      {:hackney, "~> 1.9"},
      {:sweet_xml, "~> 0.6"},
  • Download all deps, use mix deps.get

  • Prepare your AWS S3. :) Please read more in their documentation.

  • Prepare your account, we will use AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY. Please visit here for more information about ExAWS:

Let's Code

My code structure will be like this:

- root
-- elixir_exploration
-- elixir_exploration_web
--- resolvers # store all GraphQL resolvers
--- schema # store all GraphQL schemas
-- schema.ex # store all GraphQL query/mutations
  • I will code at GraphQL side first (Absinthe). Please setup the Absinthe first.

You can refer this guide:

I really love most of popular library, they bring us a nice guide. :)

  • Write the resolver, I will put in elixir_exploration_web/resolvers/uploads.ex
defmodule ElixirExplorationWeb.Resolvers.Uploads do
  alias ExAws.S3

  def upload_to_aws(_, %{input: input}, _) do
    request = input.file.path
      |> S3.Upload.stream_file()
      # take care the filename, you should validate this
      |> S3.upload("upload-test-berv", "uploads/#{input.file.filename}")
      |> ExAws.request()
    case request do
      {:ok, _} -> {:ok, "Success"}
      {:error, _} -> {:error, "Please try again"}

Don't forget to update the bucket name. In that example, I use upload-test-berv as the bucket name. I use uploads/#{input.file.filename} as the target file location.

  • Write the schema, I will put in elixir_exploration_web/schema/upload_types.ex
defmodule ElixirExplorationWeb.Schema.UploadTypes do
  use Absinthe.Schema.Notation

  alias ElixirExplorationWeb.Resolvers

  object :upload_file do
    @desc """
      Upload a file
    field :upload_file, :string do
      arg(:input, non_null(:file_input))

  input_object :file_input do
    field :file, non_null(:upload)
  • Import those files into elixir_exploration_web/schema.ex
defmodule ElixirExplorationWeb.Schema do
  use Absinthe.Schema

  alias ElixirExplorationWeb.Schema


  query do


  mutation do
  • Update config, I want to setup the default region. Currently I update to config/config.exs, but feel free to add different approach for different env.
config :ex_aws,
  region: {:system, "AWS_DEFAULT_REGION"}
  • Write the, this for setup our environment variable in our system.
export AWS_ACCESS_KEY_ID=<your_access_key_id>
export AWS_SECRET_ACCESS_KEY=<your_secret_access_key>
export AWS_DEFAULT_REGION=ap-southeast-1

Feel free to use another region. :)

  • Apply the environment, you can use source

  • Run your Phoenix Server. mix phx.server

  • Test your API. Because my API locate at localhost:4000/api/graphql, so I will use that. If you set another path, please update it from my script below.

curl -X POST -F query="mutation { uploadFile(input: {file: \"my_data\"})}" -F my_data=@mix.exs -H "Accept:application/json" localhost:4000/api/graphql

Elixir Test

  • Check your S3


My Repo

You also can visit my repositories. I will write more in there if I have any updates.


Yey! Congrats! You've implemented file upload and upload the file to AWS S3. In the next section, maybe I will write to show the result after you upload the file. The approach I will use:

  1. Use database as the listing
  2. Call AWS S3 API Directly to get the list

I hope I will write in the next month and write each approach in different article.

Thank you. :)

Thank you image

The city at night via unsplash