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
endEach 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 browserPUTs each part to itsurlwith exactly itsheaders, 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 asStorehouse.Plug.Registerchecks 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 forStorehouse.Plug.Presign.- the options of
Storehouse.presign_multipart/4andStorehouse.complete_multipart/4(:accept,:max_bytes,:max_pixels,:part_bytes,:key,:cache,:metadata,:adapter), as they are.