howdy/ui/uploader
An uploader: a place to drop or choose files, which the browser sends straight to storage, showing each as an attachment with its progress.
html.form([attribute.method("post"), attribute.action("/profile")], [
uploader.new(name: "avatar", start: "/profile/uploads")
|> uploader.accept(["image/png", "image/jpeg"])
|> uploader.max_size(5_000_000)
|> uploader.layout(attachment.Tile)
|> uploader.view,
ui.submit_button(Primary, [], [text("Save")]),
])
For each file the browser asks your app for somewhere to put it, sends
it there, and once it has arrived adds a hidden input named name
holding its key. The form then posts the keys, not the files. While a
file is still on its way the form will not submit.
start is an endpoint of your own that the browser posts
{"name": "cat.png", "type": "image/png", "size": 48213} to, as JSON.
It checks the type and size, chooses a key and answers with where to
send the file:
{"key": "avatars/42/k3j…/cat.png",
"upload": {"url": "https://…", "method": "PUT", "headers": {"content-type": "image/png"}}}
With howdy_storage that is storage.upload_url and
storage.direct_upload_to_json; see its direct uploads guide. An error
response from howdy/service is shown on the file, using the message of
its first field if it has one.
The keys come back from the browser, so check each one before you use it: that it is one your app handed to this user, and that the object exists.
The sending is done by howdy/ui/behaviour, which every page includes.
In a live view, live.on_values(name, message) hears the keys each time
a file arrives or is removed.
Types
A file stored before the page was drawn, such as the current avatar, shown as already uploaded. Its key is posted with the others unless it is removed.
pub type Stored {
Stored(
key: String,
name: String,
size: Int,
thumbnail: option.Option(String),
)
}
Constructors
-
Stored( key: String, name: String, size: Int, thumbnail: option.Option(String), )
What the uploader says. too_large may contain {limit}, and
too_many {count}, for the limit.
pub type Words {
Words(
prompt: String,
remove: String,
retry: String,
uploading: String,
too_large: String,
wrong_type: String,
too_many: String,
failed: String,
wait: String,
missing: String,
)
}
Constructors
-
Words( prompt: String, remove: String, retry: String, uploading: String, too_large: String, wrong_type: String, too_many: String, failed: String, wait: String, missing: String, )
Values
pub fn accept(
uploader: Uploader,
types: List(String),
) -> Uploader
Only take files of these types: content types such as "image/png",
families such as "image/*", or extensions such as ".pdf", as in the
accept attribute. The file chooser offers only these, and other files
are refused before they are sent.
pub fn describe(name: String, size: Int) -> String
A file’s type and size as an attachment shows them, such as
"PDF · 2.4 MB", the same as the browser shows for a file just chosen.
pub fn drop_class() -> css.Class
pub fn file_size(bytes: Int) -> String
A number of bytes for people: "820 KB", "2.4 MB", "18 MB". Units
go up in thousands, with one decimal place below ten.
pub fn id(uploader: Uploader, id: String) -> Uploader
The id of the file input, for a <label for> such as a field’s.
pub fn input_class() -> css.Class
The file input, hidden but still focusable and announced.
pub fn layout(
uploader: Uploader,
layout: attachment.Layout,
) -> Uploader
Show files as rows, compact rows or tiles. Tiles suit images, which are shown as thumbnails while they upload.
pub fn max_size(uploader: Uploader, bytes: Int) -> Uploader
Refuse files over this many bytes before they are sent. Your start
endpoint must check too: this only saves a wasted request.
pub fn multiple(
uploader: Uploader,
max_files max_files: Int,
) -> Uploader
Take up to max_files files. Without this, a new file replaces the one
there.
pub fn new(name name: String, start start: String) -> Uploader
An uploader for one file, posting its key as name, that asks the
endpoint at start where to send each file.
pub fn prompt_class() -> css.Class
pub fn stored(
uploader: Uploader,
files: List(Stored),
) -> Uploader
Files already stored, shown first.
pub fn uploader_class() -> css.Class