# `Magpie.LiveView.UploadWriter`
[🔗](https://github.com/alexcassol/magpie/blob/v0.3.1/lib/magpie/live_view/upload_writer.ex#L1)

A `Phoenix.LiveView.UploadWriter` that streams an upload straight into a
Dropbox upload session — the bytes never touch your server's disk.

LiveView's default writer spools each entry into a temporary file, so a
500 MB upload is written to disk in full before `consume_uploaded_entry/3`
can hand it to `Magpie.Files.upload_file/4`. This writer skips that round
trip: chunks are buffered in memory up to `:chunk_size` and appended to an
upload session as they arrive.

## Usage

    socket =
      allow_upload(socket, :report,
        accept: ~w(.pdf),
        max_file_size: 500_000_000,
        writer: fn _name, entry, _socket ->
          {Magpie.LiveView.UploadWriter,
           client: MyApp.dropbox_client(), path: "/Reports/" <> entry.client_name}
        end
      )

`consume_uploaded_entries/3` then receives whatever `meta/1` returns, so the
Dropbox metadata of the committed file is already there — nothing left to
upload:

    consume_uploaded_entries(socket, :report, fn %{metadata: metadata}, _entry ->
      {:ok, metadata}
    end)

## Options

  * `:client` (required) — a `Magpie.Client`
  * `:path` (required) — the destination path in Dropbox
  * `:chunk_size` — bytes buffered before each append (default 8 MiB).
    Dropbox wants every append but the last to be a multiple of 4 MiB, so
    keep this a multiple of 4 MiB.
  * `:mode` — `"add"` (default) or `"overwrite"`
  * `:autorename` — default `true`
  * `:mute` — default `false`

## Notes

Magpie does not depend on `:phoenix_live_view` — the behaviour is a plain
set of callbacks, and declaring it would drag Phoenix into every project
that only wants a Dropbox client. The callbacks below match
`Phoenix.LiveView.UploadWriter` as of LiveView 1.0.

They run in the per-entry `Phoenix.LiveView.UploadChannel` process, not in
the LiveView itself: a slow append backpressures that one upload instead of
blocking the rest of the page.

The session is opened in `init/1`. A cancelled or failed upload leaves it
dangling, which is harmless — Dropbox drops incomplete sessions after 7 days
and nothing is committed without a `finish`.

# `close`

Commits the session on `:done`, sending whatever is left in the buffer along
with the finish call. Any other reason (`:cancel`, an upstream error) leaves
the session uncommitted.

# `init`

Opens the upload session. See the module docs for the accepted options.

# `meta`

What `consume_uploaded_entries/3` receives: the destination path and the
Dropbox metadata of the committed file.

# `write_chunk`

Buffers `data`, appending to the session whenever `:chunk_size` is reached.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
