use crate::Result;
use multer::Field;
use std::{
ffi::OsStr,
path::{Path, PathBuf},
};
use tempfile::Builder;
use tokio::{fs::File, io::AsyncWriteExt};
#[derive(Clone, Debug)]
pub struct FilePart {
name: Option<String>,
path: PathBuf,
size: u64,
temp_dir: PathBuf,
}
impl FilePart {
#[inline]
pub fn name(&self) -> Option<&str> {
self.name.as_deref()
}
#[inline]
pub fn name_mut(&mut self) -> Option<&mut String> {
self.name.as_mut()
}
#[inline]
pub fn path(&self) -> &PathBuf {
&self.path
}
#[inline]
pub fn temp_dir(&self) -> &PathBuf {
&self.temp_dir
}
#[inline]
pub fn size(&self) -> u64 {
self.size
}
#[inline]
pub(crate) async fn new(field: &mut Field<'_>) -> Result<Self> {
let mut path = Builder::new()
.prefix("http_multipart")
.tempdir()
.unwrap()
.into_path();
let temp_dir = path.clone();
let name = field.file_name().map(|s| s.to_owned());
path.push(
name.as_deref()
.and_then(|name| Path::new(name).extension().and_then(OsStr::to_str))
.unwrap_or("unknown"),
);
let mut file = File::create(&path).await?;
let mut size = 0;
while let Some(chunk) = field.chunk().await? {
size += chunk.len() as u64;
file.write_all(&chunk).await?;
}
Ok(Self {
name,
path,
size,
temp_dir,
})
}
}