# Image uploads

Live view has the ability to upload files. We have created a component to help with uploading a single image. This is useful for things like a user's avatar.&#x20;

```html
<!-- An example of the image upload component -->
<ImageUpload.image_input
  upload={@uploads.avatar}
  label={gettext("Avatar")}
  current_image_src={user_avatar_url(@current_user)}
  placeholder_icon="hero-user"
  on_delete="clear_avatar"
  automatic_help_text
/>
```

<figure><img src="https://content.gitbook.com/content/Yos1ARQNZ0mySw9UuAwA/blobs/jz29M8J3BHqsYcUKd9c9/Xnapper-2023-05-29-11.22.31.jpg" alt=""><figcaption><p>The &#x3C;.image_input> component</p></figcaption></figure>

For the full example, check out `edit_profile_live.ex` and `edit_profile_live.html.heex`.

### Choosing an image upload hosting provider

We have provided configuration for two hosting options: [Amazon S3](https://aws.amazon.com/s3/) and [Cloudinary](https://cloudinary.com/).

#### Amazon S3

Follow the instructions in `lib/petal_pro/file_uploads/s3.ex` to get started.

#### Cloudinary

Follow the instructions in `lib/petal_pro/file_uploads/cloudinary.ex`.&#x20;

#### Our recommendation

We recommend Cloudinary over S3 due to the fact it can do transforms on the fly simply by manipulating the URL. To do transforms in Elixir, you can use the [cloudex library](https://github.com/smeevil/cloudex).

For example, you can do the following:

```markup
  iex> Cloudex.Url.for("a_public_id")
  "//res.cloudinary.com/my_cloud_name/image/upload/a_public_id"

  iex> Cloudex.Url.for("a_public_id", %{width: 400, height: 300})
  "//res.cloudinary.com/my_cloud_name/image/upload/h_300,w_400/a_public_id"

  iex> Cloudex.Url.for("a_public_id", %{
    crop: "fill",
    fetch_format: 'auto',
    flags: 'progressive',
    width: 300,
    height: 254,
    quality: "jpegmini",
    sign_url: true
  })
  "//res.cloudinary.com/my_cloud_name/image/upload/s--jwB_Ds4w--/c_fill,f_auto,fl_progressive,h_254,q_jpegmini,w_300/a_public_id"
```

Notice you work with "public\_ids" - these are ids provided by Cloudinary. You should store these in the database instead of the URL. For example:

```elixir
cloudinary_public_ids =
  consume_uploaded_entries(socket, :avatar, fn %{fields: fields}, _entry ->
    {:ok, fields["public_id"]}
  end)
  
public_id = hd(cloudinary_public_ids)

# save public_id to the database
```
