file download
This commit is contained in:
50
Cargo.lock
generated
50
Cargo.lock
generated
@ -152,9 +152,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "axum"
|
||||
version = "0.8.8"
|
||||
version = "0.8.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b52af3cb4058c895d37317bb27508dccc8e5f2d39454016b297bf4a400597b8"
|
||||
checksum = "31b698c5f9a010f6573133b09e0de5408834d0c82f8d7475a89fc1867a71cd90"
|
||||
dependencies = [
|
||||
"axum-core",
|
||||
"axum-macros",
|
||||
@ -181,7 +181,7 @@ dependencies = [
|
||||
"sha1",
|
||||
"sync_wrapper",
|
||||
"tokio",
|
||||
"tokio-tungstenite",
|
||||
"tokio-tungstenite 0.29.0",
|
||||
"tower",
|
||||
"tower-layer",
|
||||
"tower-service",
|
||||
@ -232,9 +232,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "axum-macros"
|
||||
version = "0.5.0"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "604fde5e028fea851ce1d8570bbdc034bec850d157f7569d10f347d06808c05c"
|
||||
checksum = "7aa268c23bfbbd2c4363b9cd302a4f504fb2a9dfe7e3451d66f35dd392e20aca"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -1191,7 +1191,7 @@ dependencies = [
|
||||
"thiserror 2.0.18",
|
||||
"tokio",
|
||||
"tokio-stream",
|
||||
"tokio-tungstenite",
|
||||
"tokio-tungstenite 0.28.0",
|
||||
"tokio-util",
|
||||
"tower",
|
||||
"tower-http",
|
||||
@ -1497,7 +1497,7 @@ dependencies = [
|
||||
"subsecond",
|
||||
"thiserror 2.0.18",
|
||||
"tokio",
|
||||
"tokio-tungstenite",
|
||||
"tokio-tungstenite 0.28.0",
|
||||
"tokio-util",
|
||||
"tower",
|
||||
"tower-http",
|
||||
@ -2540,15 +2540,19 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
|
||||
name = "httpserver"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"axum-core",
|
||||
"chrono",
|
||||
"diesel",
|
||||
"dioxus",
|
||||
"dioxus-asset-resolver",
|
||||
"dioxus-html",
|
||||
"dioxus-primitives",
|
||||
"futures",
|
||||
"random-string",
|
||||
"reqwest 0.13.2",
|
||||
"serde",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
"tracing",
|
||||
"wasm-bindgen",
|
||||
"web-sys",
|
||||
@ -5226,9 +5230,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.51.0"
|
||||
version = "1.51.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2bd1c4c0fc4a7ab90fc15ef6daaa3ec3b893f004f915f2392557ed23237820cd"
|
||||
checksum = "f66bf9585cda4b724d3e78ab34b73fb2bbaba9011b9bfdf69dc836382ea13b8c"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"libc",
|
||||
@ -5284,6 +5288,18 @@ dependencies = [
|
||||
"tungstenite 0.28.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-tungstenite"
|
||||
version = "0.29.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f72a05e828585856dacd553fba484c242c46e391fb0e58917c942ee9202915c"
|
||||
dependencies = [
|
||||
"futures-util",
|
||||
"log",
|
||||
"tokio",
|
||||
"tungstenite 0.29.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-util"
|
||||
version = "0.7.18"
|
||||
@ -5561,6 +5577,22 @@ dependencies = [
|
||||
"utf-8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tungstenite"
|
||||
version = "0.29.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c01152af293afb9c7c2a57e4b559c5620b421f6d133261c60dd2d0cdb38e6b8"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"data-encoding",
|
||||
"http",
|
||||
"httparse",
|
||||
"log",
|
||||
"rand 0.9.2",
|
||||
"sha1",
|
||||
"thiserror 2.0.18",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.19.0"
|
||||
|
||||
@ -7,15 +7,19 @@ edition = "2021"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
axum-core = { version = "0.5.6", optional = true }
|
||||
chrono = { version = "0.4.44", features = ["serde"] }
|
||||
diesel = { version = "2.3.7", features = ["postgres", "r2d2"], optional = true }
|
||||
dioxus = { version = "0.7.1", features = ["router", "fullstack"] }
|
||||
dioxus-asset-resolver = "0.7.4"
|
||||
dioxus-html = "0.7.3"
|
||||
dioxus-primitives = { git = "https://github.com/DioxusLabs/components", version = "0.0.1", default-features = false }
|
||||
futures = "0.3.32"
|
||||
random-string = "1.1.0"
|
||||
reqwest = { version = "0.13.2", features = ["stream"] }
|
||||
serde = "1.0.228"
|
||||
tokio = { version = "1.51.1", optional = true }
|
||||
tokio-util = { version = "0.7.18", optional = true }
|
||||
tracing = "0.1.44"
|
||||
wasm-bindgen = "0.2.114"
|
||||
web-sys = { version = "0.3.91", features = [ "Navigator", "Clipboard" ] }
|
||||
@ -29,7 +33,7 @@ desktop = ["dioxus/desktop"]
|
||||
# The feature that are only required for the mobile = ["dioxus/mobile"] build target should be optional and only enabled in the mobile = ["dioxus/mobile"] feature
|
||||
mobile = ["dioxus/mobile"]
|
||||
# The feature that are only required for the server = ["dioxus/server"] build target should be optional and only enabled in the server = ["dioxus/server"] feature
|
||||
server = ["dioxus/server", "dep:diesel"]
|
||||
server = ["dioxus/server", "dep:diesel", "dep:tokio", "dep:tokio-util", "dep:axum-core"]
|
||||
|
||||
[profile.release]
|
||||
opt-level = "z"
|
||||
|
||||
@ -7,7 +7,6 @@
|
||||
'Noto Color Emoji';
|
||||
--font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New',
|
||||
monospace;
|
||||
--color-blue-100: oklch(93.2% 0.032 255.585);
|
||||
--color-blue-800: oklch(42.4% 0.199 265.638);
|
||||
--color-zinc-900: oklch(21% 0.006 285.885);
|
||||
--color-white: #fff;
|
||||
@ -171,6 +170,9 @@
|
||||
.static {
|
||||
position: static;
|
||||
}
|
||||
.contents {
|
||||
display: contents;
|
||||
}
|
||||
.flex {
|
||||
display: flex;
|
||||
}
|
||||
@ -192,25 +194,12 @@
|
||||
.w-screen {
|
||||
width: 100vw;
|
||||
}
|
||||
.border-collapse {
|
||||
border-collapse: collapse;
|
||||
}
|
||||
.transform {
|
||||
transform: var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,);
|
||||
}
|
||||
.resize {
|
||||
resize: both;
|
||||
}
|
||||
.flex-col {
|
||||
flex-direction: column;
|
||||
}
|
||||
.flex-row {
|
||||
flex-direction: row;
|
||||
}
|
||||
.border {
|
||||
border-style: var(--tw-border-style);
|
||||
border-width: 1px;
|
||||
}
|
||||
.bg-zinc-900 {
|
||||
background-color: var(--color-zinc-900);
|
||||
}
|
||||
@ -231,9 +220,6 @@
|
||||
--tw-font-weight: var(--font-weight-bold);
|
||||
font-weight: var(--font-weight-bold);
|
||||
}
|
||||
.text-blue-100 {
|
||||
color: var(--color-blue-100);
|
||||
}
|
||||
.text-blue-800 {
|
||||
color: var(--color-blue-800);
|
||||
}
|
||||
@ -243,10 +229,6 @@
|
||||
.underline {
|
||||
text-decoration-line: underline;
|
||||
}
|
||||
.outline {
|
||||
outline-style: var(--tw-outline-style);
|
||||
outline-width: 1px;
|
||||
}
|
||||
}
|
||||
@property --tw-rotate-x {
|
||||
syntax: "*";
|
||||
@ -268,20 +250,10 @@
|
||||
syntax: "*";
|
||||
inherits: false;
|
||||
}
|
||||
@property --tw-border-style {
|
||||
syntax: "*";
|
||||
inherits: false;
|
||||
initial-value: solid;
|
||||
}
|
||||
@property --tw-font-weight {
|
||||
syntax: "*";
|
||||
inherits: false;
|
||||
}
|
||||
@property --tw-outline-style {
|
||||
syntax: "*";
|
||||
inherits: false;
|
||||
initial-value: solid;
|
||||
}
|
||||
@layer properties {
|
||||
@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) {
|
||||
*, ::before, ::after, ::backdrop {
|
||||
@ -290,9 +262,7 @@
|
||||
--tw-rotate-z: initial;
|
||||
--tw-skew-x: initial;
|
||||
--tw-skew-y: initial;
|
||||
--tw-border-style: solid;
|
||||
--tw-font-weight: initial;
|
||||
--tw-outline-style: solid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,72 @@
|
||||
use std::fs::create_dir;
|
||||
|
||||
use dioxus::prelude::*;
|
||||
use dioxus::fullstack::FileStream;
|
||||
#[cfg(feature = "server")]
|
||||
use httpserver::models::GetFile;
|
||||
#[cfg(feature = "server")]
|
||||
use diesel::prelude::*;
|
||||
#[cfg(feature = "server")]
|
||||
use httpserver::DB;
|
||||
|
||||
#[cfg(feature = "server")]
|
||||
use httpserver::schema;
|
||||
|
||||
#[cfg(feature = "server")]
|
||||
use crate::config::ServerConfig;
|
||||
|
||||
use std::path::Path;
|
||||
|
||||
|
||||
#[cfg(feature = "server")]
|
||||
async fn create_filestream(filename: String, file: &Path) -> Result<FileStream, std::io::Error> {
|
||||
|
||||
let metadata = file.metadata()?;
|
||||
let contents = tokio::fs::File::open(&file).await?;
|
||||
let mime = dioxus_asset_resolver::native::get_mime_from_ext(
|
||||
file.extension().and_then(|s| s.to_str()),
|
||||
);
|
||||
let size = metadata.len();
|
||||
|
||||
let reader_stream = tokio_util::io::ReaderStream::new(contents);
|
||||
|
||||
let body = axum_core::body::Body::from_stream(reader_stream).into_data_stream();
|
||||
Ok(FileStream::from_raw(filename, Some(size), mime.to_string(), body))
|
||||
}
|
||||
|
||||
#[get("/upload/{id}/dl")]
|
||||
async fn download_file(id: String) -> Result<FileStream, HttpError> {
|
||||
use schema::file;
|
||||
let s_config = ServerConfig::load();
|
||||
|
||||
let result = DB.with(|pool| schema::file::table.select((file::filename))
|
||||
.filter(file::stored_filename.eq(id.clone()))
|
||||
.filter(file::deleted.eq(false))
|
||||
.load::<(String)>(&mut pool.get().unwrap()));
|
||||
|
||||
if let Err(_) = result {
|
||||
return HttpError::internal_server_error("Database request failed");
|
||||
}
|
||||
|
||||
let db_file = result.unwrap();
|
||||
|
||||
if db_file.len() == 0 {
|
||||
return HttpError::internal_server_error("The requested file does not exist");
|
||||
}
|
||||
|
||||
let file_path = s_config.upload_folder + &id;
|
||||
let path = Path::new(&file_path);
|
||||
|
||||
// create a filestream from raw to set the filename to the uploaded filename
|
||||
let fstream = create_filestream(db_file[0].clone(), path.into()).await;
|
||||
|
||||
match fstream {
|
||||
Ok(stream) => {
|
||||
Ok(stream)
|
||||
},
|
||||
Err(err) => {
|
||||
tracing::info!("Failed to open a file err : {err}");
|
||||
HttpError::internal_server_error(format!("Failed to open the file"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -29,7 +29,7 @@ struct FetchedInfo {
|
||||
}
|
||||
|
||||
|
||||
#[post("/api/upload/info")]
|
||||
#[get("/api/upload/info?filename")]
|
||||
async fn get_file_info(filename: String) -> Result<FetchedInfo, HttpError> {
|
||||
use schema::file;
|
||||
let result = DB.with(|pool| schema::file::table.select((file::filename, file::file_size, file::created_at))
|
||||
|
||||
@ -3,3 +3,6 @@ pub use create::UploadFile;
|
||||
|
||||
mod info;
|
||||
pub use info::FileInfo;
|
||||
|
||||
mod get;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user