Live Uploads
Let's learn how to add a file upload feature to your Phoenix application.
The LiveView framework supports the most common features that single-page apps must offer their users, including multipart uploads. LiveView can give us highly interactive file uploads, right out of the box.
In this lesson, we’ll add a file upload feature to our application. We’ll use LiveView to display upload progress and feedback while editing and saving uploaded files. When we’re done, we’ll have all the tools we need to handle complex forms, even those that require file uploads.
We’ll add file uploads to the ProductLive
form so users can choose an image to upload and associate with the product in a database. Let’s plan this new feature first. We’ll start on the backend by adding an image_upload
field to the table and schema for products. Then, we’ll update the ProductLive.FormComponent
to support file uploads. Finally, the LiveView should report on upload progress and other bits of upload feedback.
Let’s get started!
Persisting product images
We’ll start in the backend by updating the products
table and Product
schema to store an attribute image_upload
, pointing to the location of the uploaded file. Once we have our backend wired up, we’ll be able to update our LiveView’s form to accommodate file uploads.
We’ll start at the database layer by generating a migration to add a field,
:image_upload
to the products
table.
First, generate our migration file by typing the following command in the terminal below:
mix ecto.gen.migration add_image_to_products
This creates a migration file for us. After adding content to the change
function, our migration file should look like this:
defmodule Pento.Repo.Migrations.AddImageToProducts douse Ecto.Migrationdef change doalter table(:products) doadd :image_upload, :stringendendend
This code will add the new database field when we run the migration. Let’s do that now. Go to the terminal below and type in the following command:
mix ecto.migrate
The output should look something like this:
...[info] == Running 20201231152152 Pento.Repo.Migrations.AddImageToProducts.change/0 forward10:22:24.034 [info] alter table products10:22:24.041 [info] == Migrated 20201231152152 in 0.0s
This migration added a new column :image_upload
, of type :string
, to the products
table, but our schema still needs attention.
To do so, we updated the corresponding Product
schema by adding the new :image_upload
field to the schema function in pento/lib/pento/catalog/product.ex
, like this:
defmodule Pento.Catalog.Product douse Ecto.Schemaimport Ecto.Changesetschema "products" dofield :description, :stringfield :name, :stringfield :sku, :integerfield :unit_price, :floatfield :image_upload, :stringtimestamps()endend
Remember, the changeset cast/4
function must explicitly allowlist new fields,
so we added the :image_upload
attribute as well like this: ...