Impl OptionalFromRequest on MultipartFile and change behaviour on MultipartFiles to contain 0 files
This commit is contained in:
@ -1,10 +1,11 @@
|
||||
use axum::{
|
||||
extract::{
|
||||
FromRequest, Multipart, Request,
|
||||
multipart::{Field, MultipartError, MultipartRejection},
|
||||
},
|
||||
response::IntoResponse,
|
||||
};
|
||||
use axum::extract::FromRequest;
|
||||
use axum::extract::Multipart;
|
||||
use axum::extract::OptionalFromRequest;
|
||||
use axum::extract::Request;
|
||||
use axum::extract::multipart::Field;
|
||||
use axum::extract::multipart::MultipartError;
|
||||
use axum::extract::multipart::MultipartRejection;
|
||||
use axum::response::IntoResponse;
|
||||
use mime::Mime;
|
||||
use std::str::FromStr;
|
||||
use thiserror::Error;
|
||||
@ -140,6 +141,40 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> OptionalFromRequest<S> for MultipartFile
|
||||
where
|
||||
S: Send + Sync,
|
||||
{
|
||||
type Rejection = MultipartFileRejection;
|
||||
|
||||
/// Extracts a single file from a multipart request.
|
||||
/// Expects exactly one file. A file must have a name, bytes and optionally a content type.
|
||||
/// This extractor consumes the request and must ble placed last in the handler.
|
||||
/// # Example
|
||||
/// ```
|
||||
/// use std::io::Read;
|
||||
/// use axum::response::Html;
|
||||
/// use lib::axum::extractor::{MultipartFile, MultipartFiles};
|
||||
///
|
||||
/// async fn upload_file(opt_file: Option<MultipartFile>) -> Html<String> {
|
||||
/// Html(opt_file
|
||||
/// .map(|MultipartFile(file)| String::from_utf8(file.bytes).unwrap())
|
||||
/// .unwrap_or_else(|| String::from("<p>Not Found</p>"))
|
||||
/// )
|
||||
/// }
|
||||
/// ```
|
||||
async fn from_request(req: Request, state: &S) -> Result<Option<Self>, Self::Rejection> {
|
||||
let multipart = Multipart::from_request(req, state).await?;
|
||||
let files = get_files(multipart).await?;
|
||||
if files.len() > 1 {
|
||||
Err(MultipartFileRejection::SeveralFiles)
|
||||
} else {
|
||||
let file = files.first().ok_or(MultipartFileRejection::NoFiles)?;
|
||||
Ok(Some(MultipartFile(file.clone())))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> FromRequest<S> for MultipartFiles
|
||||
where
|
||||
S: Send + Sync,
|
||||
@ -147,7 +182,7 @@ where
|
||||
type Rejection = MultipartFileRejection;
|
||||
|
||||
/// Extracts multiple files from a multipart request.
|
||||
/// Expects at least one file. A file must have a name, bytes and optionally a content type.
|
||||
/// Can contain 0 files. A file must have a name, bytes and optionally a content type.
|
||||
/// This extractor consumes the request and must ble placed last in the handler.
|
||||
/// # Example
|
||||
/// ```
|
||||
@ -167,11 +202,7 @@ where
|
||||
async fn from_request(req: Request, state: &S) -> Result<Self, Self::Rejection> {
|
||||
let multipart = Multipart::from_request(req, state).await?;
|
||||
let files = get_files(multipart).await?;
|
||||
if files.is_empty() {
|
||||
Err(MultipartFileRejection::NoFiles)
|
||||
} else {
|
||||
Ok(MultipartFiles(files))
|
||||
}
|
||||
Ok(MultipartFiles(files))
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user