return the file

This commit is contained in:
blek 2023-10-11 07:55:36 +10:00
parent 7d4f771b3d
commit 92b8ebffb3
Signed by: blek
GPG Key ID: 14546221E3595D0C
3 changed files with 54 additions and 5 deletions

View File

@ -40,6 +40,7 @@ impl FileManager {
} }
fn save_int(self: &Self, file: &File, key: String) -> Result<(), Box<dyn Error>> { fn save_int(self: &Self, file: &File, key: String) -> Result<(), Box<dyn Error>> {
log::debug!("Saving a file with key: {key}");
let mut conn = self.conn.get_connection()?; let mut conn = self.conn.get_connection()?;
conn.set(key, serde_json::to_string(&file)?)?; conn.set(key, serde_json::to_string(&file)?)?;
Ok(()) Ok(())

View File

@ -3,7 +3,6 @@
use std::{sync::Arc, error::Error, ops::Add}; use std::{sync::Arc, error::Error, ops::Add};
use chrono::{DateTime, Local}; use chrono::{DateTime, Local};
use num::BigUint;
use sha2::{Sha512, Digest, digest::FixedOutput}; use sha2::{Sha512, Digest, digest::FixedOutput};
use serde::{Serialize, Deserialize}; use serde::{Serialize, Deserialize};
use tokio::fs; use tokio::fs;
@ -15,7 +14,7 @@ pub mod lookup;
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct File { pub struct File {
pub path: String, pub path: String,
pub size: BigUint, pub size: usize,
pub name: Option<String>, pub name: Option<String>,
pub mime: String, pub mime: String,
pub delete_at: DateTime<Local>, pub delete_at: DateTime<Local>,
@ -31,6 +30,32 @@ impl File {
self.sha512.clone() self.sha512.clone()
} }
pub async fn read(self: &Self) -> Result<Vec<u8>, Box<dyn Error>> {
let data = self.read_unchecked().await?;
let hash = hex::encode(Sha512::digest(data.as_slice()));
if self.hash() != hash {
return Err("File is corrupted".into());
}
Ok(data)
}
pub async fn read_unchecked(self: &Self) -> Result<Vec<u8>, Box<dyn Error>> {
let data = fs::read(self.path.clone()).await?;
if self.size == data.len() {
return Ok(data);
}
let mut ndata = Vec::<u8>::new();
for byte in data.iter() {
ndata.push(byte.clone());
if ndata.len() == self.size {
break;
}
}
Ok(ndata)
}
pub async fn create(data: Vec<u8>, mime: String, name: Option<String>, env: Env) -> Result<File, Box<dyn Error>> { pub async fn create(data: Vec<u8>, mime: String, name: Option<String>, env: Env) -> Result<File, Box<dyn Error>> {
let mut filename = String::new(); let mut filename = String::new();
@ -54,7 +79,7 @@ impl File {
Ok( Ok(
File { File {
path: path.display().to_string(), path: path.display().to_string(),
size: BigUint::from(data.len()), size: data.len(),
name: Some(filename), name: Some(filename),
mime, mime,
delete_at: expires, delete_at: expires,

View File

@ -1,9 +1,32 @@
use warp::{Filter, reply::{Reply, html}, reject::Rejection}; use warp::{Filter, reply::{Reply, html}, reject::Rejection};
use super::state::SharedState; use super::{state::SharedState, rejection::HttpReject};
pub async fn uploaded((file, _state): (String, SharedState)) -> Result<Box<dyn Reply>, Rejection> { pub async fn uploaded((file, _state): (String, SharedState)) -> Result<Box<dyn Reply>, Rejection> {
Ok(Box::new(html(file)))
let mut file_res = _state.file_mgr.find_by_hash(file.clone())
.map_err(|x| warp::reject::custom(HttpReject::StringError(x.to_string())))?;
if file_res.is_none() {
file_res = _state.file_mgr.find_by_name(file.clone())
.map_err(|x| warp::reject::custom(HttpReject::StringError(x.to_string())))?;
}
if file_res.is_none() {
return Ok(
Box::new(warp::reply::with_status("Not found", warp::http::StatusCode::NOT_FOUND))
)
}
let file_res = file_res.unwrap();
Ok(
Box::new(
warp::reply::with_header(
file_res.read_unchecked().await.unwrap(),
"Content-Type", file_res.mime
)
)
)
} }
pub fn get_uploaded(state: SharedState) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone { pub fn get_uploaded(state: SharedState) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {