nherzing

nherzing

Handling live upload timeouts

I’m wondering if there is a way to be notified of the scenario where an in-progress LiveView Upload times-out and is canceled. In my experience, the upload entry is silently removed from socket.assigns.uploads.upload_name.entries without alerting the owning liveview in any way. This makes it difficult to tell what actually happened and to act accordingly. Is there some api that I am missing or some other way of handling this that I haven’t thought of?

Detailed Reproduction and Explanation

Suppose we have the following liveview with a form with a single live upload.

defmodule MyAppWeb.SimpleLive do
  use MyAppWeb, :live_view

  def mount(_params, _session, socket) do
    {:ok,
     socket
     |> allow_upload(:my_upload,
       accept: ~w(image/jpeg image/png),
       auto_upload: true,
       progress: &handle_progress/3,
       # very low to reproduce timeouts
       chunk_timeout: 1
     )
     |> assign(progress: 0, submitted: false)}
  end

  defp handle_progress(:my_upload, entry, socket) do
    IO.inspect(entry.progress, label: "Progress")
    {:noreply, assign(socket, progress: entry.progress)}
  end

  def handle_event("validate", _params, socket) do
    IO.inspect("VALIDATE")
    {:noreply, socket}
  end

  def handle_event("save", _params, socket) do
    IO.puts("SUBMIT")
    IO.inspect(socket.assigns.uploads, label: "Uploads")
    {:noreply, assign(socket, submitted: true)}
  end

  def render(assigns) do
    ~H"""
    <form class="group" id="upload-form" phx-submit="save" phx-change="validate">
      <label class="block">
        <.live_file_input upload={@uploads.my_upload} class="hidden" /> Upload
      </label>
      <div><%= @progress %> / 100</div>

      <button type="submit">Submit</button>

      <div class="hidden group-[.phx-submit-loading]:block ">
        Submitting
      </div>
      <%= inspect(@uploads[:my_upload]) %>
    </form>

    <div>Submitted: <%= @submitted %></div>
    """
  end
end

If you attempt to upload a file with this liveview, you’ll notice that the progress is updated on the first chunk upload. After that, the upload is canceled because we hit the very low chunk_timeout. (It’s set so low to force the reproduction. You can also reproduce by leaving it at the default of 10s and change your network speed via Chrome dev tools.) At this point, the entry is removed but our liveview was not notified of this and thus cannot update its state to reflect it. Thus, our progress state remains in a broken state.

Is there any way for our liveview to respond to the fact that the upload was canceled and that the entry has been removed? Of course we could conditionally render content based on the contents of socket.assigns.uploads.my_upload.entries but that feels wrong and doesn’t solve the problem of our assigns being in a weird state.

First Post!

sodapopcan

sodapopcan

This doesn’t feel wrong to me. You can fix the assigns by that checking my_upload.entries in the :my_upload callback and cleaning them up if it’s empty. Maybe someone else has a fancier solution but that’s how I would do it without a second thought :sweat_smile:

You can of course additionally also set some error state when this happens.

Where Next?

Popular in Questions Top

vonH
When I run the Plug and I recompile I wind up having to use Ctrl C to quit iex and start again. Witht the help of rlwrap I can use the cu...
New
lanycrost
Hi everyone! I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New
mcarvalho
What is the difference between System.get_env and Application.get_env? For example, what are best practices to use one versus another.
New
Darmani72
If I have a post route which an argument: post /my_post_route/:my_param1, MyController.my_post_handler How would get the post params ...
New
joeerl
Hello again - after a longish gap I’ve decided I really must dig into Elixir and see what’s been happening here - so I have a few questio...
New
siddhant3030
Hi, I have to write a raw query for one of my project. But till now I have used ecto queries and don’t have much experience writing raw ...
New
marius95
Hello everyone, I try to use an Javascript Event Handler in my root.html.leex file. Therefore I created a function in the app.js file: ...
New

Other popular topics Top

hariharasudhan94
I would like to know what is the best IDE for elixir development?
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
AstonJ
Seen any cool LiveView demos, sample apps or examples? Please post them here! :003:
New
TunkShif
This post is an instruction guide to help you setup your Neovim for Elixir development from scratch. It includes general information on h...
274 42716 114
New
sergio
Kind of like when jquery came out, it was super necessary. Existing drag and drop libraries have a bunch of baggage to support old browse...
New
senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New

We're in Beta

About us Mission Statement