Storehouse.Tus.Plug (Storehouse v0.2.0)

Copy Markdown View Source

Resumable uploads through the app, by the tus protocol (1.0.0): for clients that speak it (Uppy's Tus plugin, tus-js-client, the mobile and desktop clients), and for stores the browser cannot send to straight (the local disk). A connection lost halfway carries on from the last byte the app has.

# lib/my_app_web/router.ex, behind your authentication
forward "/files/tus", Storehouse.Tus.Plug,
  owner: &MyAppWeb.Files.owner/1,
  room: &MyAppWeb.Files.room/1,
  accept: ["video/mp4", "video/quicktime"],
  max_bytes: 20_000_000_000,
  then: &MyAppWeb.Files.uploaded/2

and Storehouse.Tus in the app's supervision tree, where the uploads in progress are kept. For a browser that can send straight to a bucket, Storehouse.Plug.Multipart keeps the bytes out of the app altogether.

Extensions

creation (and creation-with-upload: the first bytes with the POST), termination (DELETE) and expiration (Upload-Expires; an upload not finished in :expires_in is given up). Upload-Metadata's filename and filetype (or name and type) are the file's name and claimed type.

Where the bytes go

On a store of multipart uploads (Storehouse.S3), into its multipart upload as they come, a part at a time (:part_bytes); the bytes past the last whole part wait in the upload's state until the next. On another (Storehouse.Local), into a file of :dir on the app's disk, stored when it is whole. Either way the file is checked as every upload is: its claimed type, size and the owner's room when it is created, its type by its first bytes when it is whole, and deleted when it is not what it said.

Options

  • :owner, :room, :existing - functions of the conn, as for Storehouse.Plug.Presign. A request for an upload of another owner is answered 404.
  • :accept, :max_bytes (sent as Tus-Max-Size), :max_pixels, :metadata, :cache_control, :adapter - as for Storehouse.store/2.
  • :then - a function of the conn and the stored file, called when the upload is whole and checked, that gives the conn: to save the file in a record, to send its key in a header.
  • :expires_in - seconds an upload has to finish. The default is a day.
  • :max_uploads - the uploads one owner may have in progress at once: another is refused with 429. The default is 10. Those in progress count against the owner's :room too, by their sizes. (With a :state that has Storehouse.Tus.State.owned/1.)
  • :part_bytes - the parts of a multipart upload, at least 5 MiB. The default is 8 MiB.
  • :dir - the directory of the uploads to a store without multipart uploads. The default is storehouse-tus in the system's temporary directory: on several nodes, one they share.
  • :state - where uploads are kept between requests, a module of Storehouse.Tus.State. The default is Storehouse.Tus.State.ETS.

Why not tussle

tussle (a fork of the tus package) is a tus server for Elixir with storage of its own (the disk, S3 through ExAws). Storehouse writes through its own stores instead, with no dependency, and checks a file as every other upload is checked; the protocol itself is small.