mirror of
https://git.asonix.dog/asonix/pict-rs.git
synced 2024-11-28 20:41:00 +00:00
Remove unneeded mime conversions
This commit is contained in:
parent
e720ed6af2
commit
6f04595c3b
5 changed files with 62 additions and 73 deletions
|
@ -140,14 +140,6 @@ pub(crate) enum Format {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Format {
|
impl Format {
|
||||||
pub(crate) fn to_mime(&self) -> mime::Mime {
|
|
||||||
match self {
|
|
||||||
Format::Jpeg => mime::IMAGE_JPEG,
|
|
||||||
Format::Png => mime::IMAGE_PNG,
|
|
||||||
Format::Webp => "image/webp".parse().unwrap(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn to_magick_format(&self) -> &'static str {
|
pub(crate) fn to_magick_format(&self) -> &'static str {
|
||||||
match self {
|
match self {
|
||||||
Format::Jpeg => "JPEG",
|
Format::Jpeg => "JPEG",
|
||||||
|
|
|
@ -19,7 +19,15 @@ pub(crate) fn details_hint(filename: &str) -> Option<ValidInputType> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
pub(crate) fn image_webp() -> mime::Mime {
|
||||||
|
"image/webp".parse().unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn video_mp4() -> mime::Mime {
|
||||||
|
"video/mp4".parse().unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug)]
|
||||||
pub(crate) enum ValidInputType {
|
pub(crate) enum ValidInputType {
|
||||||
Mp4,
|
Mp4,
|
||||||
Gif,
|
Gif,
|
||||||
|
@ -38,6 +46,24 @@ impl ValidInputType {
|
||||||
Self::Webp => "WEBP",
|
Self::Webp => "WEBP",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn to_ext(&self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
Self::Mp4 => ".mp4",
|
||||||
|
Self::Gif => ".gif",
|
||||||
|
Self::Png => ".png",
|
||||||
|
Self::Jpeg => ".jpeg",
|
||||||
|
Self::Webp => ".webp",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn from_format(format: Format) -> Self {
|
||||||
|
match format {
|
||||||
|
Format::Jpeg => ValidInputType::Jpeg,
|
||||||
|
Format::Png => ValidInputType::Png,
|
||||||
|
Format::Webp => ValidInputType::Webp,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -157,11 +183,11 @@ fn parse_details(s: std::borrow::Cow<'_, str>) -> Result<Details, Error> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let mime_type = match format {
|
let mime_type = match format {
|
||||||
"MP4" => crate::validate::video_mp4(),
|
"MP4" => video_mp4(),
|
||||||
"GIF" => mime::IMAGE_GIF,
|
"GIF" => mime::IMAGE_GIF,
|
||||||
"PNG" => mime::IMAGE_PNG,
|
"PNG" => mime::IMAGE_PNG,
|
||||||
"JPEG" => mime::IMAGE_JPEG,
|
"JPEG" => mime::IMAGE_JPEG,
|
||||||
"WEBP" => crate::validate::image_webp(),
|
"WEBP" => image_webp(),
|
||||||
_ => return Err(UploadError::UnsupportedFormat.into()),
|
_ => return Err(UploadError::UnsupportedFormat.into()),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,6 @@ use self::{
|
||||||
migrate::LatestDb,
|
migrate::LatestDb,
|
||||||
store::Store,
|
store::Store,
|
||||||
upload_manager::{Details, UploadManager, UploadManagerSession},
|
upload_manager::{Details, UploadManager, UploadManagerSession},
|
||||||
validate::{image_webp, video_mp4},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const MEGABYTES: usize = 1024 * 1024;
|
const MEGABYTES: usize = 1024 * 1024;
|
||||||
|
@ -740,7 +739,7 @@ where
|
||||||
.transform_error(transform_error)
|
.transform_error(transform_error)
|
||||||
.field(
|
.field(
|
||||||
"images",
|
"images",
|
||||||
Field::array(Field::file(move |filename, content_type, stream| {
|
Field::array(Field::file(move |filename, _, stream| {
|
||||||
let manager = manager2.clone();
|
let manager = manager2.clone();
|
||||||
|
|
||||||
let span = tracing::info_span!("file-import", ?filename);
|
let span = tracing::info_span!("file-import", ?filename);
|
||||||
|
@ -752,7 +751,6 @@ where
|
||||||
.session()
|
.session()
|
||||||
.import(
|
.import(
|
||||||
filename,
|
filename,
|
||||||
content_type,
|
|
||||||
validate_imports,
|
validate_imports,
|
||||||
map_error::map_crate_error(stream),
|
map_error::map_crate_error(stream),
|
||||||
)
|
)
|
||||||
|
@ -837,7 +835,6 @@ async fn main() -> anyhow::Result<()> {
|
||||||
|
|
||||||
let manager = UploadManager::new(store, db, CONFIG.format()).await?;
|
let manager = UploadManager::new(store, db, CONFIG.format()).await?;
|
||||||
|
|
||||||
// TODO: move restructure to FileStore
|
|
||||||
manager.restructure().await?;
|
manager.restructure().await?;
|
||||||
launch(manager).await
|
launch(manager).await
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
error::{Error, UploadError},
|
error::{Error, UploadError},
|
||||||
|
magick::ValidInputType,
|
||||||
migrate::{alias_id_key, alias_key},
|
migrate::{alias_id_key, alias_key},
|
||||||
store::Store,
|
store::Store,
|
||||||
upload_manager::{
|
upload_manager::{
|
||||||
|
@ -142,7 +143,6 @@ where
|
||||||
pub(crate) async fn import(
|
pub(crate) async fn import(
|
||||||
mut self,
|
mut self,
|
||||||
alias: String,
|
alias: String,
|
||||||
content_type: mime::Mime,
|
|
||||||
validate: bool,
|
validate: bool,
|
||||||
mut stream: impl Stream<Item = Result<web::Bytes, Error>> + Unpin,
|
mut stream: impl Stream<Item = Result<web::Bytes, Error>> + Unpin,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
|
@ -197,7 +197,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
debug!("Validating bytes");
|
debug!("Validating bytes");
|
||||||
let (content_type, validated_reader) = crate::validate::validate_image_bytes(
|
let (input_type, validated_reader) = crate::validate::validate_image_bytes(
|
||||||
bytes_mut.freeze(),
|
bytes_mut.freeze(),
|
||||||
self.manager.inner.format.clone(),
|
self.manager.inner.format.clone(),
|
||||||
true,
|
true,
|
||||||
|
@ -214,10 +214,10 @@ where
|
||||||
let hash = hasher_reader.finalize_reset().await?;
|
let hash = hasher_reader.finalize_reset().await?;
|
||||||
|
|
||||||
debug!("Adding alias");
|
debug!("Adding alias");
|
||||||
self.add_alias(&hash, content_type.clone()).await?;
|
self.add_alias(&hash, input_type).await?;
|
||||||
|
|
||||||
debug!("Saving file");
|
debug!("Saving file");
|
||||||
self.save_upload(&identifier, hash, content_type).await?;
|
self.save_upload(&identifier, hash, input_type).await?;
|
||||||
|
|
||||||
// Return alias to file
|
// Return alias to file
|
||||||
Ok(self)
|
Ok(self)
|
||||||
|
@ -228,9 +228,9 @@ where
|
||||||
&self,
|
&self,
|
||||||
identifier: &S::Identifier,
|
identifier: &S::Identifier,
|
||||||
hash: Hash,
|
hash: Hash,
|
||||||
content_type: mime::Mime,
|
input_type: ValidInputType,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let (dup, name) = self.check_duplicate(hash, content_type).await?;
|
let (dup, name) = self.check_duplicate(hash, input_type).await?;
|
||||||
|
|
||||||
// bail early with alias to existing file if this is a duplicate
|
// bail early with alias to existing file if this is a duplicate
|
||||||
if dup.exists() {
|
if dup.exists() {
|
||||||
|
@ -246,15 +246,15 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
// check for an already-uploaded image with this hash, returning the path to the target file
|
// check for an already-uploaded image with this hash, returning the path to the target file
|
||||||
#[instrument(skip(self, hash, content_type))]
|
#[instrument(skip(self, hash, input_type))]
|
||||||
async fn check_duplicate(
|
async fn check_duplicate(
|
||||||
&self,
|
&self,
|
||||||
hash: Hash,
|
hash: Hash,
|
||||||
content_type: mime::Mime,
|
input_type: ValidInputType,
|
||||||
) -> Result<(Dup, String), Error> {
|
) -> Result<(Dup, String), Error> {
|
||||||
let main_tree = self.manager.inner.main_tree.clone();
|
let main_tree = self.manager.inner.main_tree.clone();
|
||||||
|
|
||||||
let filename = self.next_file(content_type).await?;
|
let filename = self.next_file(input_type).await?;
|
||||||
|
|
||||||
let filename2 = filename.clone();
|
let filename2 = filename.clone();
|
||||||
let hash2 = hash.as_slice().to_vec();
|
let hash2 = hash.as_slice().to_vec();
|
||||||
|
@ -287,11 +287,11 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
// generate a short filename that isn't already in-use
|
// generate a short filename that isn't already in-use
|
||||||
#[instrument(skip(self, content_type))]
|
#[instrument(skip(self, input_type))]
|
||||||
async fn next_file(&self, content_type: mime::Mime) -> Result<String, Error> {
|
async fn next_file(&self, input_type: ValidInputType) -> Result<String, Error> {
|
||||||
loop {
|
loop {
|
||||||
debug!("Filename generation loop");
|
debug!("Filename generation loop");
|
||||||
let filename = file_name(Uuid::new_v4(), content_type.clone())?;
|
let filename = file_name(Uuid::new_v4(), input_type);
|
||||||
|
|
||||||
let identifier_tree = self.manager.inner.identifier_tree.clone();
|
let identifier_tree = self.manager.inner.identifier_tree.clone();
|
||||||
let filename2 = filename.clone();
|
let filename2 = filename.clone();
|
||||||
|
@ -319,9 +319,9 @@ where
|
||||||
// Add an alias to an existing file
|
// Add an alias to an existing file
|
||||||
//
|
//
|
||||||
// This will help if multiple 'users' upload the same file, and one of them wants to delete it
|
// This will help if multiple 'users' upload the same file, and one of them wants to delete it
|
||||||
#[instrument(skip(self, hash, content_type))]
|
#[instrument(skip(self, hash, input_type))]
|
||||||
async fn add_alias(&mut self, hash: &Hash, content_type: mime::Mime) -> Result<(), Error> {
|
async fn add_alias(&mut self, hash: &Hash, input_type: ValidInputType) -> Result<(), Error> {
|
||||||
let alias = self.next_alias(hash, content_type).await?;
|
let alias = self.next_alias(hash, input_type).await?;
|
||||||
|
|
||||||
self.store_hash_id_alias_mapping(hash, &alias).await?;
|
self.store_hash_id_alias_mapping(hash, &alias).await?;
|
||||||
|
|
||||||
|
@ -365,11 +365,15 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate an alias to the file
|
// Generate an alias to the file
|
||||||
#[instrument(skip(self, hash, content_type))]
|
#[instrument(skip(self, hash, input_type))]
|
||||||
async fn next_alias(&mut self, hash: &Hash, content_type: mime::Mime) -> Result<String, Error> {
|
async fn next_alias(
|
||||||
|
&mut self,
|
||||||
|
hash: &Hash,
|
||||||
|
input_type: ValidInputType,
|
||||||
|
) -> Result<String, Error> {
|
||||||
loop {
|
loop {
|
||||||
debug!("Alias gen loop");
|
debug!("Alias gen loop");
|
||||||
let alias = file_name(Uuid::new_v4(), content_type.clone())?;
|
let alias = file_name(Uuid::new_v4(), input_type);
|
||||||
self.alias = Some(alias.clone());
|
self.alias = Some(alias.clone());
|
||||||
|
|
||||||
let res = self.save_alias_hash_mapping(hash, &alias).await?;
|
let res = self.save_alias_hash_mapping(hash, &alias).await?;
|
||||||
|
@ -407,20 +411,6 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn file_name(name: Uuid, content_type: mime::Mime) -> Result<String, Error> {
|
fn file_name(name: Uuid, input_type: ValidInputType) -> String {
|
||||||
Ok(format!("{}{}", name, to_ext(content_type)?))
|
format!("{}{}", name, input_type.to_ext())
|
||||||
}
|
|
||||||
|
|
||||||
fn to_ext(mime: mime::Mime) -> Result<&'static str, Error> {
|
|
||||||
if mime == mime::IMAGE_PNG {
|
|
||||||
Ok(".png")
|
|
||||||
} else if mime == mime::IMAGE_JPEG {
|
|
||||||
Ok(".jpg")
|
|
||||||
} else if mime == crate::video_mp4() {
|
|
||||||
Ok(".mp4")
|
|
||||||
} else if mime == crate::image_webp() {
|
|
||||||
Ok(".webp")
|
|
||||||
} else {
|
|
||||||
Err(UploadError::UnsupportedFormat.into())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,14 +5,6 @@ use actix_web::web::Bytes;
|
||||||
use tokio::io::AsyncRead;
|
use tokio::io::AsyncRead;
|
||||||
use tracing::instrument;
|
use tracing::instrument;
|
||||||
|
|
||||||
pub(crate) fn image_webp() -> mime::Mime {
|
|
||||||
"image/webp".parse().unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn video_mp4() -> mime::Mime {
|
|
||||||
"video/mp4".parse().unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
struct UnvalidatedBytes {
|
struct UnvalidatedBytes {
|
||||||
bytes: Bytes,
|
bytes: Bytes,
|
||||||
written: usize,
|
written: usize,
|
||||||
|
@ -45,56 +37,48 @@ pub(crate) async fn validate_image_bytes(
|
||||||
bytes: Bytes,
|
bytes: Bytes,
|
||||||
prescribed_format: Option<Format>,
|
prescribed_format: Option<Format>,
|
||||||
validate: bool,
|
validate: bool,
|
||||||
) -> Result<(mime::Mime, impl AsyncRead + Unpin), Error> {
|
) -> Result<(ValidInputType, impl AsyncRead + Unpin), Error> {
|
||||||
let input_type = crate::magick::input_type_bytes(bytes.clone()).await?;
|
let input_type = crate::magick::input_type_bytes(bytes.clone()).await?;
|
||||||
|
|
||||||
if !validate {
|
if !validate {
|
||||||
let mime_type = match input_type {
|
return Ok((input_type, Either::left(UnvalidatedBytes::new(bytes))));
|
||||||
ValidInputType::Gif => video_mp4(),
|
|
||||||
ValidInputType::Mp4 => mime::IMAGE_GIF,
|
|
||||||
ValidInputType::Jpeg => mime::IMAGE_JPEG,
|
|
||||||
ValidInputType::Png => mime::IMAGE_PNG,
|
|
||||||
ValidInputType::Webp => image_webp(),
|
|
||||||
};
|
|
||||||
|
|
||||||
return Ok((mime_type, Either::left(UnvalidatedBytes::new(bytes))));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
match (prescribed_format, input_type) {
|
match (prescribed_format, input_type) {
|
||||||
(_, ValidInputType::Gif) => Ok((
|
(_, ValidInputType::Gif) => Ok((
|
||||||
video_mp4(),
|
ValidInputType::Mp4,
|
||||||
Either::right(Either::left(crate::ffmpeg::to_mp4_bytes(
|
Either::right(Either::left(crate::ffmpeg::to_mp4_bytes(
|
||||||
bytes,
|
bytes,
|
||||||
InputFormat::Gif,
|
InputFormat::Gif,
|
||||||
)?)),
|
)?)),
|
||||||
)),
|
)),
|
||||||
(_, ValidInputType::Mp4) => Ok((
|
(_, ValidInputType::Mp4) => Ok((
|
||||||
video_mp4(),
|
ValidInputType::Mp4,
|
||||||
Either::right(Either::left(crate::ffmpeg::to_mp4_bytes(
|
Either::right(Either::left(crate::ffmpeg::to_mp4_bytes(
|
||||||
bytes,
|
bytes,
|
||||||
InputFormat::Mp4,
|
InputFormat::Mp4,
|
||||||
)?)),
|
)?)),
|
||||||
)),
|
)),
|
||||||
(Some(Format::Jpeg) | None, ValidInputType::Jpeg) => Ok((
|
(Some(Format::Jpeg) | None, ValidInputType::Jpeg) => Ok((
|
||||||
mime::IMAGE_JPEG,
|
ValidInputType::Jpeg,
|
||||||
Either::right(Either::right(Either::left(
|
Either::right(Either::right(Either::left(
|
||||||
crate::exiftool::clear_metadata_bytes_read(bytes)?,
|
crate::exiftool::clear_metadata_bytes_read(bytes)?,
|
||||||
))),
|
))),
|
||||||
)),
|
)),
|
||||||
(Some(Format::Png) | None, ValidInputType::Png) => Ok((
|
(Some(Format::Png) | None, ValidInputType::Png) => Ok((
|
||||||
mime::IMAGE_PNG,
|
ValidInputType::Png,
|
||||||
Either::right(Either::right(Either::left(
|
Either::right(Either::right(Either::left(
|
||||||
crate::exiftool::clear_metadata_bytes_read(bytes)?,
|
crate::exiftool::clear_metadata_bytes_read(bytes)?,
|
||||||
))),
|
))),
|
||||||
)),
|
)),
|
||||||
(Some(Format::Webp) | None, ValidInputType::Webp) => Ok((
|
(Some(Format::Webp) | None, ValidInputType::Webp) => Ok((
|
||||||
image_webp(),
|
ValidInputType::Webp,
|
||||||
Either::right(Either::right(Either::right(Either::left(
|
Either::right(Either::right(Either::right(Either::left(
|
||||||
crate::magick::clear_metadata_bytes_read(bytes)?,
|
crate::magick::clear_metadata_bytes_read(bytes)?,
|
||||||
)))),
|
)))),
|
||||||
)),
|
)),
|
||||||
(Some(format), _) => Ok((
|
(Some(format), _) => Ok((
|
||||||
format.to_mime(),
|
ValidInputType::from_format(format),
|
||||||
Either::right(Either::right(Either::right(Either::right(
|
Either::right(Either::right(Either::right(Either::right(
|
||||||
crate::magick::convert_bytes_read(bytes, format)?,
|
crate::magick::convert_bytes_read(bytes, format)?,
|
||||||
)))),
|
)))),
|
||||||
|
|
Loading…
Reference in a new issue