# `Storehouse.Plug.Multipart`
[🔗](https://github.com/hattoriai/storehouse/blob/v0.2.0/lib/storehouse/plug/multipart.ex#L1)

Very large files sent from the browser straight to the store in parts
(`Storehouse.presign_multipart/4`), for the JavaScript client or a
frontend of the app's own: JSON endpoints beside `Storehouse.Plug.Presign`.

    # lib/my_app_web/router.ex, behind your authentication
    scope "/files" do
      pipe_through [:files, :require_user]  # the guide's, with its CSRF check

      forward "/multipart", Storehouse.Plug.Multipart,
        owner: &MyAppWeb.Files.owner/1,
        room: &MyAppWeb.Files.room/1,
        accept: ["video/mp4", "video/quicktime", "application/zip"],
        max_bytes: 20_000_000_000
    end

Each is a `POST` of JSON:

  * `start` - `{"name", "type", "bytes", "checksum"}`: `{"upload": {"key",
    "upload_id", "part_bytes", "parts", "token"}}`, or `{"existing": file}`
    for a file the app has already.
  * `sign` - `{"key", "upload_id", "token", "parts": [{"number",
    "checksum"}]}`, up to 1,000 parts, each with its SHA-256 in Base64:
    `{"parts": [{"number", "method", "url", "headers"}]}`. The browser
    `PUT`s each part to its `url` with exactly its `headers`, and the
    part's size is signed: the store takes only that many bytes.
  * `list` - `{"key", "upload_id", "token"}`: `{"parts": [{"number",
    "bytes", "checksum"}]}`, those the store has, for a browser reloaded
    halfway.
  * `complete` - `{"key", "upload_id", "token", "name"}`: `{"file": file}`
    or `{"existing": file}`, checked as `Storehouse.Plug.Register` checks
    one; `{"error": "missing_parts"}` or `"wrong_size"` (and the upload
    stays) when the store does not have it all.
  * `abort` - `{"key", "upload_id", "token"}`: `{"ok": true}`.

The token is the upload `start` signed (its key, its owner, its size and
its parts, with the endpoint's `secret_key_base`, for a week): a request
without the token of its upload is refused with `403` and `{"error":
"invalid_token"}`, so that no one signs, completes or gives up another's
upload, or one larger than it said. A body that is not the JSON above
gives `400`, a body that is not `application/json` `415`, and a refusal of
the file `422`, with `{"error": code}`.

## Options

  * `:owner`, `:room`, `:existing` - functions of the conn, as for
    `Storehouse.Plug.Presign`.
  * the options of `Storehouse.presign_multipart/4` and
    `Storehouse.complete_multipart/4` (`:accept`, `:max_bytes`,
    `:max_pixels`, `:part_bytes`, `:key`, `:cache`, `:metadata`,
    `:adapter`), as they are.

---

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