aboutsummaryrefslogtreecommitdiffstats
path: root/src/file_op.rs
diff options
context:
space:
mode:
authorSven-Hendrik Haase <svenstaro@gmail.com>2025-03-07 10:00:48 +0000
committerSven-Hendrik Haase <svenstaro@gmail.com>2025-03-07 11:14:03 +0000
commit11ea8a19d1481b0660e5a2765da6e67d3e8aa72c (patch)
tree341cb7ac4bd5915deb8fe58947b3cc352687556d /src/file_op.rs
parentReformat style.scss (diff)
downloadminiserve-11ea8a19d1481b0660e5a2765da6e67d3e8aa72c.tar.gz
miniserve-11ea8a19d1481b0660e5a2765da6e67d3e8aa72c.zip
Add asynchronous directory size counting
This is enabled by default and without an option to toggle it off as it's asynchronous and shouldn't block the server thread.
Diffstat (limited to '')
-rw-r--r--src/file_op.rs34
1 files changed, 33 insertions, 1 deletions
diff --git a/src/file_op.rs b/src/file_op.rs
index 4319410..149cd2a 100644
--- a/src/file_op.rs
+++ b/src/file_op.rs
@@ -4,6 +4,7 @@ use std::io::ErrorKind;
use std::path::{Component, Path, PathBuf};
use actix_web::{HttpRequest, HttpResponse, http::header, web};
+use async_walkdir::{Filtering, WalkDir};
use futures::{StreamExt, TryStreamExt};
use log::{info, warn};
use serde::Deserialize;
@@ -38,6 +39,37 @@ impl FileHash {
}
}
+/// Get the recursively calculated dir size for a given dir
+///
+/// Expects `dir` to be sanitized. This function doesn't do any sanitization itself.
+pub async fn recursive_dir_size(dir: &Path) -> Result<u64, RuntimeError> {
+ let mut entries = WalkDir::new(dir).filter(|entry| async move {
+ if let Ok(metadata) = entry.metadata().await {
+ if metadata.is_file() {
+ return Filtering::Continue;
+ }
+ }
+ Filtering::Ignore
+ });
+
+ let mut total_size = 0;
+ loop {
+ match entries.next().await {
+ Some(Ok(entry)) => {
+ if let Ok(metadata) = entry.metadata().await {
+ total_size += metadata.len();
+ }
+ }
+ Some(Err(e)) => {
+ warn!("Error trying to read file when calculating dir size: {e}");
+ return Err(RuntimeError::InvalidPathError(e.to_string()));
+ }
+ None => break,
+ }
+ }
+ Ok(total_size)
+}
+
/// Saves file data from a multipart form field (`field`) to `file_path`. Optionally overwriting
/// existing file and comparing the uploaded file checksum to the user provided `file_hash`.
///
@@ -329,7 +361,7 @@ pub async fn upload_file(
query: web::Query<FileOpQueryParameters>,
payload: web::Payload,
) -> Result<HttpResponse, RuntimeError> {
- let conf = req.app_data::<MiniserveConfig>().unwrap();
+ let conf = req.app_data::<web::Data<MiniserveConfig>>().unwrap();
let upload_path = sanitize_path(&query.path, conf.show_hidden).ok_or_else(|| {
RuntimeError::InvalidPathError("Invalid value for 'path' parameter".to_string())
})?;