Elixir Phoenix

Learn how to configure an Elixir Phoenix App for use with Filebase.

What is Elixir Phoenix?

Elixir Phoenix is a web framework built using the Elixir programming language. It is designed to help developers quickly build scalable and fault-tolerant web applications that can handle large amounts of traffic. Phoenix provides many features that are common to modern web frameworks, including a request/response cycle, a routing system, controllers, views, and templates. It is a popular choice for building real-time applications, such as chat apps, games, and social media platforms, as well as traditional web applications.

Read below to learn how to use Elixir Phoenix with Filebase.

Prerequisites:

1. Create a new Elixir project with the command:

mix phx.new file_upload_app

cd file_upload_app

2. Next, create a new database with the command:

mix ecto.create

3. Then, add the Ex.Aws.S3 package to your Elixir list of dependencies in your project’s mix.esc file:

{:ex_aws, "~> 2.0"},
{:ex_aws_s3, "~> 2.0"},
{:poison, "~> 3.0"},
{:hackney, "~> 1.9"},
{:sweet_xml, "~> 0.6.6"},

4. Install these dependencies with the command:

mix deps.get

5. Configure the Ex.Aws.S3 package to use your FIlebase instance with the following configuration in your project’s config/config.exs file:

config :ex_aws, 
access_key_id: System.get_env("AWS_ACCESS_KEY_ID"),          
secret_access_key: System.get_env("AWS_SECRET_ACCESS_KEY"),
s3: [ 
 scheme: "https://", 
 host: "bucket-name.s3.filebase.com", 
 region: "us-east-1" 
]

Replace ‘bucket-name’ with your Filebase bucket name.

6. Create a .env file with the following environment variables:

export AWS_ACCESS_KEY_ID=FILEBASE_ACCESS_KEY
export AWS_SECRET_ACCESS_KEY=FILEBASE_SECRET_KEY

7. Then, source this environmental variable file with the command:

source .env

8. Next, in the lib/file_upload_app_web/router.ex file, add the following code:

scope “/, FileUploadAppWeb do 
 pipe_through :browser 
 resources “/upload”, UploadController, only: [:create, :new]
end

9. Create a new migration with the command:

mix ecto.gen.migration add_uploads

10. This command will create a new file located at priv/repo/migrations/add_uploads.exs. Open this file and insert the following code:

defmodule FileUploadApp.Repo.Migrations.AddUploads do
  use Ecto.Migration

  def change do
    create table(:uploads) do
      add :image_url, :string
      timestamps()
  end
end
end

11. Then apply the changes to the Elixir project with the command:

mix ecto.migrate

12. Within the file_upload_app_web folder, create a new folder called models, with a new file inside called upload.ex. Insert the following code:

defmodule FileUploadApp.Upload do
  use FileUploadApp.Web, :model
  schema "uploads" do
    field :image_url, :string

    timestamps()
  end
  def changeset(struct, params \\\\ :invalid) do
    struct
    |> cast(params, [:image_url])
    |> validate_required([:image_url])
  end
end

13. Next, within the templates folder, create a new folder called upload, then within that folder create a new file called new.html.eex. Inside this new file, insert the following:

<%= form_for @changeset, upload_path(@conn, :create), [multipart: true] fn f -> %>
  <div class="form-group">    
    <%= label f, :image, class: "control-label" %>    
    <%= file_input f, :image, class: "form-control" %>    
    <%= error_tag f, :image %>  
  </div>
  <%= submit "Upload Image", class: "btn" %>
<% end %>

14. Lastly, create a new upload_controller.ex file in the controllers folder. Add the following code to the file:

defmodule FileUploadApp.UploadController do
 use FileUploadApp.Web, :controller
 alias FileUploadApp.Upload
 def new(conn, _params) do
  changeset = Upload.changeset(%Upload{})
  render conn, "new.html", changeset: changeset
 end
def create(conn, %{"upload" => %{"image" => image_params} = upload_params}) do
  file_uuid = UUID.uuid4(:hex)        
  image_filename = image_params.filename
  unique_filename = "#{file_uuid}-#{image_filename}"
  {:ok, image_binary} = File.read(image_params.path)           
  bucket_name = System.get_env("BUCKET_NAME")
  image = 
    ExAws.S3.put_object(bucket_name, unique_filename, image_binary)          
    |> ExAws.request!
  
  updated_params = 
    upload_params          
    |> Map.update(image, image_params, fn _value -> "https://#{bucket_name}.s3.filebase.com/#{unique_filename}" end)
  changeset = Upload.changeset(%Upload{}, updated_params)
  case Repo.insert!(changeset) do
    {:ok, upload} ->
        conn
        |> put_flash(:info, "Image uploaded successfully!")
        |> redirect(to: upload_path(conn, :new))
    {:error, changeset} ->
        render conn, "new.html", changeset: changeset
  end
end
end

15. Now it’s time to start the server. Use the command:

mix phoenix.server

16. The server will start on localhost:4000. Open this in a web browser, then go to localhost:4000/uploads/new to upload a file.

Last updated