return the file
This commit is contained in:
parent
7d4f771b3d
commit
92b8ebffb3
|
@ -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(())
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
Loading…
Reference in New Issue