Storehouse.Plug.Multipart (Storehouse v0.2.0)

Copy Markdown View Source

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 PUTs 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