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: github.com/stavro/arc
Preparation
- 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 phx.new elixir_exploration
Note:
- Phoenix Installation Documentation
- Phoenix Generate Project
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.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"},
]
end
Download all deps, use
mix deps.get
Prepare your AWS S3. :) Please read more in their documentation. aws.amazon.com/s3
Prepare your account, we will use
AWS_ACCESS_KEY_ID
andAWS_SECRET_ACCESS_KEY
. Please visit here for more information aboutExAWS
: github.com/ex-aws/ex_aws
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: hexdocs.pm/absinthe/plug-phoenix.html
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
IO.inspect(input.file)
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"}
end
end
end
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
import_types(Absinthe.Plug.Types)
object :upload_file do
@desc """
Upload a file
"""
field :upload_file, :string do
arg(:input, non_null(:file_input))
resolve(&Resolvers.Uploads.upload_to_aws/3)
end
end
input_object :file_input do
field :file, non_null(:upload)
end
end
- Import those files into
elixir_exploration_web/schema.ex
defmodule ElixirExplorationWeb.Schema do
use Absinthe.Schema
alias ElixirExplorationWeb.Schema
import_types(Schema.UploadTypes)
query do
end
mutation do
import_fields(:upload_file)
end
end
- 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
env.sh
, 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 env.sh
.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
- Check your S3
My Repo
You also can visit my repositories. I will write more in there if I have any updates.
Congrats
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:
- Use database as the listing
- 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. :)
The city at night via unsplash