pub struct MultipartData {
pub fields: Vec<Field>,
}Expand description
Container for all multipart form data fields.
MultipartData provides convenient access methods for working with
collections of multipart fields. It allows you to query fields by name,
filter by type (text vs. file), and iterate over all fields.
This container is returned by Multipart::collect_all() and provides
a higher-level interface for accessing parsed multipart data.
§Field Access Patterns
The container provides several ways to access fields:
- By name: Get specific fields using
get_field()orget_fields() - By type: Filter text fields with
text_fields()or files withfile_fields() - Direct access: Iterate over all fields using
fields
§Examples
§Accessing Specific Fields
use ignitia::multipart::MultipartData;
async fn process_form(data: MultipartData) -> Result<(), Box<dyn std::error::Error>> {
// Get a specific field by name
if let Some(email_field) = data.get_field("email") {
let email = email_field.text().await?;
println!("Email: {}", email);
}
// Get all fields with the same name (e.g., multiple file uploads)
let photo_fields = data.get_fields("photos");
for photo in photo_fields {
if let Some(filename) = photo.file_name() {
println!("Photo: {}", filename);
}
}
Ok(())
}§Processing by Field Type
async fn categorize_fields(data: MultipartData) -> Result<(), Box<dyn std::error::Error>> {
// Process all text fields
println!("Text fields:");
for field in data.text_fields() {
let value = field.text().await?;
println!(" {}: {}", field.name(), value);
}
// Process all file uploads
println!("File uploads:");
for field in data.file_fields() {
let filename = field.file_name().unwrap_or("unnamed");
println!(" {}: {} ({})", field.name(), filename,
field.content_type().unwrap_or("unknown"));
}
Ok(())
}Fields§
§fields: Vec<Field>Vector containing all parsed fields in order
Implementations§
Source§impl MultipartData
impl MultipartData
Sourcepub fn get_fields(&self, name: &str) -> Vec<&Field>
pub fn get_fields(&self, name: &str) -> Vec<&Field>
Returns all fields that have the specified name.
This method is useful when multiple fields share the same name, such as multiple file uploads or checkbox values. It returns references to all matching fields in the order they appeared in the multipart data.
§Arguments
name- The field name to search for
§Returns
A vector of references to fields with the matching name. Returns an empty vector if no fields match.
§Examples
use ignitia::multipart::MultipartData;
async fn process_photos(data: MultipartData) -> Result<(), Box<dyn std::error::Error>> {
// Get all photo uploads (multiple files with same field name)
let photos = data.get_fields("photos");
println!("Found {} photos", photos.len());
for (i, photo) in photos.iter().enumerate() {
let filename = photo.file_name().unwrap_or(&format!("photo_{}", i));
println!("Photo {}: {}", i + 1, filename);
// Save each photo
let saved = photo.save_to_file(format!("uploads/{}", filename)).await?;
println!(" Saved {} bytes", saved.size);
}
Ok(())
}§Performance
This method performs a linear search through all fields, so its performance is O(n) where n is the total number of fields.
Sourcepub fn get_field(&self, name: &str) -> Option<&Field>
pub fn get_field(&self, name: &str) -> Option<&Field>
Returns the first field with the specified name.
This is a convenience method for accessing single-valued fields where you expect only one field with the given name. If multiple fields have the same name, only the first one is returned.
§Arguments
name- The field name to search for
§Returns
Some(field)- Reference to the first field with the matching nameNone- No field found with the specified name
§Examples
use ignitia::multipart::MultipartData;
async fn get_user_info(data: MultipartData) -> Result<(), Box<dyn std::error::Error>> {
// Get individual form fields
let username = match data.get_field("username") {
Some(field) => field.text().await?,
None => return Err("Username field is required".into()),
};
let email = match data.get_field("email") {
Some(field) => field.text().await?,
None => return Err("Email field is required".into()),
};
// Optional profile picture
if let Some(profile_pic) = data.get_field("profile_picture") {
if profile_pic.is_file() {
let saved_file = profile_pic.save_to_file("uploads/profile.jpg").await?;
println!("Profile picture saved: {} bytes", saved_file.size);
}
}
println!("User: {} ({})", username, email);
Ok(())
}§Use Cases
- Single-value form fields (username, email, etc.)
- Optional file uploads
- Configuration parameters
- Any field where you expect at most one value
Sourcepub fn text_fields(&self) -> Vec<&Field>
pub fn text_fields(&self) -> Vec<&Field>
Returns all fields that are text fields (not file uploads).
This method filters the fields to return only those that represent regular form inputs like text boxes, textareas, hidden fields, etc. It excludes any fields that represent file uploads.
§Returns
A vector of references to all text fields in the order they appeared in the multipart data.
§Examples
§Processing Form Data
use ignitia::multipart::MultipartData;
use std::collections::HashMap;
async fn extract_form_data(data: MultipartData) -> Result<HashMap<String, String>, Box<dyn std::error::Error>> {
let mut form_data = HashMap::new();
// Convert all text fields to a key-value map
for field in data.text_fields() {
let name = field.name().to_string();
let value = field.text().await?;
form_data.insert(name, value);
}
Ok(form_data)
}§Validation
async fn validate_required_fields(data: MultipartData) -> Result<(), String> {
let required_fields = vec!["username", "email", "password"];
let text_fields = data.text_fields();
for required in required_fields {
let found = text_fields.iter().any(|field| field.name() == required);
if !found {
return Err(format!("Required field '{}' is missing", required));
}
}
Ok(())
}§Field Classification
A field is considered a text field if:
- It does not have a filename in its Content-Disposition header
- It is not stored as a temporary file on disk
This includes:
- Regular text inputs
- Hidden fields
- Textareas
- Select boxes
- Radio buttons and checkboxes
Sourcepub fn file_fields(&self) -> Vec<&Field>
pub fn file_fields(&self) -> Vec<&Field>
Returns all fields that represent file uploads.
This method filters the fields to return only those that represent file uploads, identified by having a filename in the Content-Disposition header or being stored as temporary files due to their size.
§Returns
A vector of references to all file fields in the order they appeared in the multipart data.
§Examples
§Processing File Uploads
use ignitia::multipart::MultipartData;
async fn save_all_uploads(data: MultipartData) -> Result<(), Box<dyn std::error::Error>> {
let uploads_dir = "uploads";
std::fs::create_dir_all(uploads_dir)?;
let mut saved_files = Vec::new();
for (i, field) in data.file_fields().iter().enumerate() {
let filename = field.file_name()
.map(|s| s.to_string())
.unwrap_or_else(|| format!("upload_{}", i));
let file_path = format!("{}/{}", uploads_dir, filename);
let saved_file = field.save_to_file(&file_path).await?;
saved_files.push(saved_file);
println!("Saved: {} ({} bytes)", file_path, saved_file.size);
}
println!("Total files saved: {}", saved_files.len());
Ok(())
}§File Analysis
async fn analyze_uploads(data: MultipartData) -> Result<(), Box<dyn std::error::Error>> {
let file_fields = data.file_fields();
println!("Upload Summary:");
println!(" Total files: {}", file_fields.len());
let mut total_size = 0u64;
let mut content_types = std::collections::HashMap::new();
for field in file_fields {
// Get file size
let bytes = field.bytes().await?;
total_size += bytes.len() as u64;
// Track content types
let content_type = field.content_type().unwrap_or("unknown");
*content_types.entry(content_type).or_insert(0) += 1;
println!(" - {} ({}): {} bytes",
field.name(),
field.file_name().unwrap_or("unnamed"),
bytes.len()
);
}
println!(" Total size: {} bytes", total_size);
println!(" Content types: {:?}", content_types);
Ok(())
}§File Detection
A field is considered a file upload if:
- It has a
filenameparameter in its Content-Disposition header, OR - It was written to a temporary file due to exceeding the memory threshold
This covers:
- Explicit file uploads via
<input type="file"> - Large text fields that overflow to disk storage
- Binary data submitted through form fields