5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

LiveView Uploadを実装してみる

Last updated at Posted at 2024-09-09

参考資料

  • allow_uploadでアップロードできるファイルを指定
  • live_file_inputタグはファイルの受付画面を作る
  • handle_event("validate", _params, socket)で検証
  • handle_event("save", _params, socket)で保存

プロジェクトの準備

$ phx.new upload_experiment --no-ecto

ソース追加

lib/upload_experiment_web/live/upload_live.ex
defmodule UploadExperimentWeb.UploadLive do
  use UploadExperimentWeb, :live_view

  @impl Phoenix.LiveView
  def mount(_params, _session, socket) do
    {:ok,
    socket
    |> assign(:uploaded_files, [])
    |> allow_upload(:avatar, accept: ~w(.png), max_entries: 2)}
  end

  @impl Phoenix.LiveView
  def handle_event("validate", _params, socket) do
    {:noreply, socket}
  end

  @impl Phoenix.LiveView
  def handle_event("cancel-upload", %{"ref" => ref}, socket) do
    {:noreply, cancel_upload(socket, :avatar, ref)}
  end

  @impl Phoenix.LiveView
  def handle_event("save", _params, socket) do
    uploaded_files =
      consume_uploaded_entries(socket, :avatar, fn %{path: path}, _entry ->
        dest = Path.join("priv/static/images/uploads", Path.basename(path))
        # You will need to create `priv/static/uploads` for `File.cp!/2` to work.
        File.cp!(path, dest)
        {:ok, ~p"/images/uploads/#{Path.basename(dest)}"}
      end)

    {:noreply, update(socket, :uploaded_files, &(&1 ++ uploaded_files))}
  end

  defp error_to_string(:too_large), do: "Too large"
  defp error_to_string(:too_many_files), do: "You have selected too many files"
  defp error_to_string(:not_accepted), do: "You have selected an unacceptable file type"
end
lib/upload_experiment_web/live/upload_live.html.heex
<form id="upload-form" phx-submit="save" phx-change="validate">
    <.live_file_input upload={@uploads.avatar} />
    <button type="submit">Upload</button>
</form>

<section phx-drop-target={@uploads.avatar.ref}>
<%!-- render each avatar entry --%>
<%= for entry <- @uploads.avatar.entries do %>
  <article class="upload-entry">

    <figure>
      <.live_img_preview entry={entry} />
      <figcaption><%= entry.client_name %></figcaption>
    </figure>

    <%!-- entry.progress will update automatically for in-flight entries --%>
    <progress value={entry.progress} max="100"> <%= entry.progress %>% </progress>

    <%!-- a regular click event whose handler will invoke Phoenix.LiveView.cancel_upload/3 --%>
    <button type="button" phx-click="cancel-upload" phx-value-ref={entry.ref} aria-label="cancel">&times;</button>

    <%!-- Phoenix.Component.upload_errors/2 returns a list of error atoms --%>
    <%= for err <- upload_errors(@uploads.avatar, entry) do %>
      <p class="alert alert-danger"><%= error_to_string(err) %></p>
    <% end %>

  </article>
<% end %>

<%!-- Phoenix.Component.upload_errors/1 returns a list of error atoms --%>
<%= for err <- upload_errors(@uploads.avatar) do %>
  <p class="alert alert-danger"><%= error_to_string(err) %></p>
<% end %>

</section>
lib/upload_experiment_web/router.ex
defmodule UploadExperimentWeb.Router do
  # 〜省略〜
  scope "/", UploadExperimentWeb do
    pipe_through :browser

+   live "/up", UploadLive, :index

    get "/", PageController, :home
  end
  # 〜省略〜
end
下記のフォルダーを作成する
priv/static/images/uploads

実行

下記にアクセス
http://localhost:4000/up

image.png

ファイル選択後
image.png

「Upload」クリック後のファイルのアップロードを確認
image.png

ソース(github)

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?