# Elixir Phoenix

## 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.

{% hint style="success" %}

## Prerequisites:

* [x] [Download and install](https://elixir-lang.org/install.html) Elixir.
* [x] [Download and install](https://www.postgresql.org/download/) PostgreSQL.
* [x] [Sign up](https://filebase.com/signup) for a free Filebase account.
* [x] Have your Filebase Access and Secret Keys. Learn how to view your access keys [here](https://docs.filebase.com/getting-started-guides/getting-started-guide#working-with-access-keys).
* [x] Create a Filebase IPFS Bucket. Learn how to create a bucket [here](https://docs.filebase.com/getting-started-guides/getting-started-guide#creating-and-working-with-buckets).
  {% endhint %}

### 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:

```elixir
{: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:

```elixir
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:

```elixir
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:

```elixir
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:

```elixir
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:

```elixir
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:

```elixir
<%= 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:

```elixir
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.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.filebase.com/code-development-+-sdks/code-development/elixir-phoenix.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
