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.
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
defpdepsdo[...# 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
Prepare your account, we will use AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY. Please visit here for more information about ExAWS: https://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.
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
defmoduleElixirExplorationWeb.Resolvers.UploadsdoaliasExAws.S3defupload_to_aws(_,%{input:input},_)doIO.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()caserequestdo{:ok,_}->{:ok,"Success"}{:error,_}->{:error,"Please try again"}endendend
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
defmoduleElixirExplorationWeb.Schema.UploadTypesdouseAbsinthe.Schema.NotationaliasElixirExplorationWeb.Resolversimport_types(Absinthe.Plug.Types)object:upload_filedo@desc"""
Upload a file
"""field:upload_file,:stringdoarg(:input,non_null(:file_input))resolve(&Resolvers.Uploads.upload_to_aws/3)endendinput_object:file_inputdofield:file,non_null(:upload)endend
Import those files into elixir_exploration_web/schema.ex
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 -Fquery="mutation { uploadFile(input: {file: \"my_data\"})}"-Fmy_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.
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.