pub struct MultipartForm { /* private fields */ }Expand description
The parsed parts of a multipart body: text fields and files, by field name.
Obtained from the Multipart extractor. Text fields are read with
MultipartForm::form (all at once, into a struct) or
MultipartForm::text (one by one); files are taken with
MultipartForm::file. Parts without a name are skipped; a text
field that is not UTF-8 is a 400.
§Examples
use ocre::storage::MultipartForm;
// An empty form, as `Default` builds it.
let mut form = MultipartForm::default();
assert_eq!(form.text("title"), None);
assert!(form.file("image").is_none());Implementations§
Source§impl MultipartForm
impl MultipartForm
Sourcepub fn form<T: DeserializeOwned>(&self) -> Result<T>
pub fn form<T: DeserializeOwned>(&self) -> Result<T>
Deserializes the text fields into T, exactly like axum’s Form.
Numbers and booleans are parsed from their text, #[serde(default)]
fills in missing fields, and file fields are ignored. Unchecked HTML
checkboxes send nothing, so give bool fields #[serde(default)].
§Errors
Error::BadRequest (400) Invalid form: ... when a field is missing
or T cannot parse it.
§Examples
use serde::Deserialize;
#[derive(Deserialize)]
struct Profile {
name: String,
age: u8,
#[serde(default)]
public: bool,
}
let body = "--x\r\nContent-Disposition: form-data; name=\"name\"\r\n\r\nAda\r\n\
--x\r\nContent-Disposition: form-data; name=\"age\"\r\n\r\n36\r\n--x--\r\n";
let request = Request::post("/profile")
.header("content-type", "multipart/form-data; boundary=x")
.body(Body::from(body))
.unwrap();
let Multipart(form) = block_on(Multipart::<1024>::from_request(request, &())).unwrap();
let profile: Profile = form.form()?;
assert_eq!((profile.name.as_str(), profile.age, profile.public), ("Ada", 36, false));
#[derive(Debug, Deserialize)]
struct Strict {
#[allow(dead_code)]
email: String,
}
let err = form.form::<Strict>().unwrap_err();
assert!(matches!(err, ocre::Error::BadRequest(message) if message == "Invalid form: missing field `email`"));Sourcepub fn text(&self, name: &str) -> Option<&str>
pub fn text(&self, name: &str) -> Option<&str>
Returns the first text field named name, or None when it was not sent.
File fields are not text fields: use MultipartForm::file for them.
§Examples
let body = "--x\r\nContent-Disposition: form-data; name=\"title\"\r\n\r\nHoliday\r\n--x--\r\n";
let request = Request::post("/photos")
.header("content-type", "multipart/form-data; boundary=x")
.body(Body::from(body))
.unwrap();
let Multipart(form) = block_on(Multipart::<1024>::from_request(request, &())).unwrap();
assert_eq!(form.text("title"), Some("Holiday"));
assert_eq!(form.text("missing"), None);Sourcepub fn file(&mut self, name: &str) -> Option<Upload>
pub fn file(&mut self, name: &str) -> Option<Upload>
Takes the first file sent as name, leaving the others.
None when the field is missing or no file was chosen (browsers then
send an empty, nameless file, which is dropped while parsing). Taking
moves the Upload out without copying its bytes; a second call for
the same name returns the next file with that name, if any.
§Examples
let body = "--x\r\n\
Content-Disposition: form-data; name=\"image\"; filename=\"C:\\\\photos\\\\beach.png\"\r\n\
Content-Type: Image/PNG\r\n\r\n\
PNG...\r\n\
--x\r\n\
Content-Disposition: form-data; name=\"notes\"; filename=\"\"\r\n\
Content-Type: application/octet-stream\r\n\r\n\
\r\n\
--x--\r\n";
let request = Request::post("/photos")
.header("content-type", "multipart/form-data; boundary=x")
.body(Body::from(body))
.unwrap();
let Multipart(mut form) = block_on(Multipart::<1024>::from_request(request, &())).unwrap();
let image = form.file("image").unwrap();
assert_eq!(image.filename, "beach.png");
assert_eq!(image.content_type, "image/png");
assert_eq!(image.size(), 6);
assert!(form.file("image").is_none()); // taken
assert!(form.file("notes").is_none()); // no file chosenSourcepub fn files(&mut self, name: &str) -> Vec<Upload>
pub fn files(&mut self, name: &str) -> Vec<Upload>
Takes every file sent as name or name[] (an <input type="file" multiple>), in order.
§Examples
let body = "--x\r\nContent-Disposition: form-data; name=\"photos\"; filename=\"a.png\"\r\n\
Content-Type: image/png\r\n\r\nA\r\n\
--x\r\nContent-Disposition: form-data; name=\"photos\"; filename=\"b.png\"\r\n\
Content-Type: image/png\r\n\r\nB\r\n--x--\r\n";
let request = Request::post("/albums/1/photos")
.header("content-type", "multipart/form-data; boundary=x")
.body(Body::from(body))
.unwrap();
let Multipart(mut form) = block_on(Multipart::<1024>::from_request(request, &())).unwrap();
let names: Vec<String> = form.files("photos").into_iter().map(|file| file.filename).collect();
assert_eq!(names, ["a.png", "b.png"]);
assert!(form.files("photos").is_empty()); // takenTrait Implementations§
Source§impl Clone for MultipartForm
impl Clone for MultipartForm
Source§fn clone(&self) -> MultipartForm
fn clone(&self) -> MultipartForm
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for MultipartForm
impl Debug for MultipartForm
Source§impl Default for MultipartForm
impl Default for MultipartForm
Source§fn default() -> MultipartForm
fn default() -> MultipartForm
Source§impl PartialEq for MultipartForm
impl PartialEq for MultipartForm
Source§fn eq(&self, other: &MultipartForm) -> bool
fn eq(&self, other: &MultipartForm) -> bool
self and other values to be equal, and is used by ==.