75 lines
2.0 KiB
Rust
75 lines
2.0 KiB
Rust
use crate::constants;
|
|
use actix_multipart::form::MultipartForm;
|
|
use actix_multipart::form::tempfile::TempFile;
|
|
use actix_web::dev::Payload;
|
|
use actix_web::{Error, FromRequest, HttpRequest};
|
|
use mime_guess::Mime;
|
|
use std::io::Read;
|
|
use std::str::FromStr;
|
|
|
|
#[derive(Debug, MultipartForm)]
|
|
struct FileUploadForm {
|
|
#[multipart(rename = "file")]
|
|
file: TempFile,
|
|
}
|
|
|
|
pub struct FileExtractor {
|
|
pub buff: Vec<u8>,
|
|
pub mime: Mime,
|
|
pub name: Option<String>,
|
|
}
|
|
|
|
impl FileExtractor {
|
|
pub fn name(&self) -> String {
|
|
match &self.name {
|
|
None => {
|
|
let ext = self.mime.suffix().map(|s| s.as_str()).unwrap_or("bin");
|
|
format!("file.{ext}")
|
|
}
|
|
Some(f) => f.to_string(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl FromRequest for FileExtractor {
|
|
type Error = Error;
|
|
type Future = futures_util::future::LocalBoxFuture<'static, Result<Self, Self::Error>>;
|
|
|
|
fn from_request(req: &HttpRequest, payload: &mut Payload) -> Self::Future {
|
|
let form = MultipartForm::<FileUploadForm>::from_request(req, payload);
|
|
|
|
Box::pin(async move {
|
|
let mut form = form.await?;
|
|
|
|
if form.file.size > constants::MAX_UPLOAD_FILE_SIZE {
|
|
return Err(actix_web::error::ErrorPayloadTooLarge(
|
|
"Uploaded file is too large!",
|
|
));
|
|
}
|
|
|
|
let mut buff = Vec::with_capacity(form.file.size);
|
|
form.file.file.read_to_end(&mut buff)?;
|
|
|
|
let mime = match form
|
|
.file
|
|
.content_type
|
|
.clone()
|
|
.or_else(|| Mime::from_str(form.file.file_name.as_deref().unwrap_or("")).ok())
|
|
{
|
|
Some(s) => s,
|
|
None => {
|
|
return Err(actix_web::error::ErrorBadRequest(
|
|
"Mimetype was not specified!!",
|
|
));
|
|
}
|
|
};
|
|
|
|
Ok(Self {
|
|
mime,
|
|
buff,
|
|
name: form.file.file_name.clone(),
|
|
})
|
|
})
|
|
}
|
|
}
|