feat: show download size on files read from disk
This commit is contained in:
parent
b8611e6415
commit
b44fa6c4a1
|
@ -43,13 +43,13 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "async-trait"
|
||||
version = "0.1.59"
|
||||
version = "0.1.68"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "31e6e93155431f3931513b243d371981bb2770112b370c82745a1d19d2f99364"
|
||||
checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.104",
|
||||
"syn 2.0.22",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -135,6 +135,7 @@ dependencies = [
|
|||
"async-recursion",
|
||||
"axum",
|
||||
"bytes",
|
||||
"futures",
|
||||
"hyper",
|
||||
"log",
|
||||
"pretty_env_logger",
|
||||
|
@ -213,6 +214,21 @@ dependencies = [
|
|||
"percent-encoding",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures"
|
||||
version = "0.3.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40"
|
||||
dependencies = [
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-executor",
|
||||
"futures-io",
|
||||
"futures-sink",
|
||||
"futures-task",
|
||||
"futures-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-channel"
|
||||
version = "0.3.28"
|
||||
|
@ -220,6 +236,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -228,6 +245,17 @@ version = "0.3.28"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c"
|
||||
|
||||
[[package]]
|
||||
name = "futures-executor"
|
||||
version = "0.3.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-task",
|
||||
"futures-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-io"
|
||||
version = "0.3.28"
|
||||
|
@ -263,9 +291,13 @@ version = "0.3.28"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533"
|
||||
dependencies = [
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-io",
|
||||
"futures-macro",
|
||||
"futures-sink",
|
||||
"futures-task",
|
||||
"memchr",
|
||||
"pin-project-lite",
|
||||
"pin-utils",
|
||||
"slab",
|
||||
|
|
|
@ -14,6 +14,7 @@ bytes = "1"
|
|||
rand = "0.8.5"
|
||||
async-recursion = "1.0.0"
|
||||
walkdir = "2"
|
||||
futures = "0.3"
|
||||
log = "0.4"
|
||||
pretty_env_logger = "0.5.0"
|
||||
archived = { path = "./archived" }
|
||||
|
|
57
src/view.rs
57
src/view.rs
|
@ -10,8 +10,8 @@ use axum::{
|
|||
};
|
||||
|
||||
use bytes::Bytes;
|
||||
use hyper::StatusCode;
|
||||
use tokio::fs::File;
|
||||
use hyper::{http::HeaderValue, StatusCode};
|
||||
use tokio::{fs::File, runtime::Handle};
|
||||
use tokio_util::io::ReaderStream;
|
||||
|
||||
pub enum ViewSuccess {
|
||||
|
@ -28,20 +28,67 @@ impl IntoResponse for ViewSuccess {
|
|||
fn into_response(self) -> Response {
|
||||
match self {
|
||||
ViewSuccess::FromDisk(file) => {
|
||||
// get handle to current runtime
|
||||
// i use this to block on futures here (not async)
|
||||
let handle = Handle::current();
|
||||
let _ = handle.enter();
|
||||
|
||||
// read the metadata of the file on disk
|
||||
// this function isn't async
|
||||
// .. so we have to use handle.block_on() to get the metadata
|
||||
let metadata = futures::executor::block_on(file.metadata());
|
||||
|
||||
// if we error then return 500
|
||||
if metadata.is_err() {
|
||||
error!("failed to read metadata from disk");
|
||||
return ViewError::InternalServerError.into_response();
|
||||
}
|
||||
|
||||
// unwrap (which we know is safe) and read the file size as a string
|
||||
let metadata = metadata.unwrap();
|
||||
let len_str = metadata.len().to_string();
|
||||
|
||||
debug!("file is {} bytes on disk", &len_str);
|
||||
|
||||
// HeaderValue::from_str will never error if only visible ASCII characters are passed (32-127)
|
||||
// .. so unwrapping this should be fine
|
||||
let content_length = HeaderValue::from_str(&len_str).unwrap();
|
||||
|
||||
// create a streamed body response (we want to stream larger files)
|
||||
let reader = ReaderStream::new(file);
|
||||
let stream = StreamBody::new(reader);
|
||||
|
||||
stream.into_response()
|
||||
// extract mutable headers from the response
|
||||
let mut res = stream.into_response();
|
||||
let headers = res.headers_mut();
|
||||
|
||||
// clear headers, browser can imply content type
|
||||
headers.clear();
|
||||
|
||||
// insert Content-Length header
|
||||
// that way the browser shows how big a file is when it's being downloaded
|
||||
headers.insert("Content-Length", content_length);
|
||||
|
||||
res
|
||||
}
|
||||
ViewSuccess::FromCache(data) => {
|
||||
// extract mutable headers from the response
|
||||
let mut res = data.into_response();
|
||||
let mut res = data.clone().into_response();
|
||||
let headers = res.headers_mut();
|
||||
|
||||
// clear the headers, let the browser imply it
|
||||
headers.clear();
|
||||
|
||||
/* // we do not need this for FromCache because it works fine
|
||||
// read the length of the data as a string
|
||||
let len_str = data.len().to_string();
|
||||
|
||||
// HeaderValue::from_str will never error if only visible ASCII characters are passed (32-127)
|
||||
// .. so this should be fine
|
||||
let content_length = HeaderValue::from_str(&len_str).unwrap();
|
||||
headers.append("Content-Length", content_length);
|
||||
*/
|
||||
|
||||
res
|
||||
}
|
||||
}
|
||||
|
@ -61,7 +108,7 @@ impl IntoResponse for ViewError {
|
|||
ViewError::InternalServerError => {
|
||||
// convert string into response, change status code
|
||||
let mut res = "internal server error!".into_response();
|
||||
*res.status_mut() = StatusCode::NOT_FOUND;
|
||||
*res.status_mut() = StatusCode::INTERNAL_SERVER_ERROR;
|
||||
|
||||
res
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue