Stef-Verniers

Stef-Verniers

I’m a bit in a fuzz about this topic. I’ve worked out some sort of Dropbox feature for a specific client. This feature allows him to upload files (zips, pdf’s, ..) up to a limit of 50. As a test, I’ve uploaded 25 pdf’s with a file size of 50mb.

During the tests, I got it working with 10 as it’s temporary limit and it needs some time, as it would just stay still on 25 files and die with a silent error in my terminal. I would like to discuss some ideas how we can make sure we can pick up all 50 files and what the most correct way would be to send them over as secure as possible with a reasonable tempo.

Any ideas?

Some details:

  • We are uploading to an Amazon S3 Bucket
  • The file uploader has a custom Write script

The uploader assign for our uploader

     |> allow_upload(:dropbox_files,
       accept: @extensions,
       validator: &validate_extension/1,
       max_entries: @max_files,
       auto_upload: true,
       chunk_size: 5 * 1024 * 1024,
       progress: &handle_progress/3,
       max_file_size: 500_000_000,
       writer: fn _name, entry, socket ->
         key =
           ClientDropbox.tmp_key(socket.assigns.client, socket.assigns.user, entry.client_name)

         {DropboxWriter, key: key, content_type: MIME.from_path(key)}
       end
     )}

Our Write file:

defmodule MyCompanyWeb.ClientDashboard.DropboxWriter do
  @behaviour Phoenix.LiveView.UploadWriter

  alias MyCompany.Helpers.FileHelpers

  @impl true
  def init(opts) do
    opts = Keyword.validate!(opts, [:content_type, :key])

    with {:ok, upload} <- FileHelpers.initiate_multipart_upload(opts[:key], opts[:content_type]) do
      {:ok, %{key: opts[:key], chunk: 1, parts: [], upload: upload}}
    end
  end

  @impl true
  def meta(state) do
    %{key: state.key, filename: Path.basename(state.key)}
  end

  @impl true
  def write_chunk(data, state) do
    case FileHelpers.upload_part(state.upload, state.chunk, data) do
      {:ok, part} ->
        {:ok, %{state | chunk: state.chunk + 1, parts: [part | state.parts]}}

      {:error, reason} ->
        {:error, reason, state}
    end
  end

  @impl true
  def close(state, :done) do
    case FileHelpers.complete_multipart_upload(state.upload, state.parts) do
      :ok -> {:ok, state}
      {:error, reason} -> {:error, reason}
    end
  end

  def close(state, _reason) do
    FileHelpers.abort_multipart_upload(state.upload)

    {:ok, state}
  end
end

Showing Posts 1 to 6

Zurga

Zurga

I ran into this issue years ago and implemented a batching algorithm. Submitted a PR but it never got merged.

Anyway, what I do now is zip all the files together and send them as one big upload. This also works but has trade-offs.

Stef-Verniers

Stef-Verniers OP

To zip all the files and send those over was something that came accross my mind as well, but I don’t think I can pull this off as we don’t store the files localy on a tmp folder first. We send them directly to S3 over the browser..

krasenyp

krasenyp

Why don’t you use direct to S3 upload, from the browser? You only presign the URLs on the backend and upload from the frontend concurrently.

Stef-Verniers

Stef-Verniers OP

Thanks for the suggestions

We got the solution by increasing the chunk_timeout to 600_000.
That did the trick!

olivermt

olivermt

Same for me, just I implemented a full queue with optional multipart.

File uploads not top of mind at the time I think :laughing:

I saw @mcrumm was working on something but unsure if it ever got merged.

Zurga

Zurga

Yeah the naive implementation that currently just starts all uploads at once is very basic. Maybe some vibecoders could get a PR going, they might get more traction :upside_down_face:

— All posts loaded —

Where Next? Top

Trending in Proposals: Ideas Top

Stef-Verniers
I’m a bit in a fuzz about this topic. I’ve worked out some sort of Dropbox feature for a specific client. This feature allows him to uplo...
New

Other Trending Topics Top

dominicletz
Hey there, I haven’t seen a list of useful Elixir specific skills for the popular AI tools yet so I’m starting one here with my first. ...
New
mudasobwa
I fully migrated to my own harness from Anthropic/Gemini and I think it’s time to share it. Welcome DSH, the DeepSeek Harness, fully writ...
New
KristerV
Hey. Is there anyone here who creates agents in their apps? Not talking about using agents, but creating them. I’m finding it pretty diff...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
webofbits
With AI doing more of the implementation work, I’ve been wondering how much coding I should deliberately keep doing myself. My main conc...
#ai
New
OndrejValenta
(I just needed to vent somewhere and LinkedIn is full of hope, or hype, I’m not sure which exactly) AI dream has many faces, but general...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews