diff options
author | Sven-Hendrik Haase <svenstaro@gmail.com> | 2025-03-07 11:38:10 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-03-07 11:38:10 +0000 |
commit | 419204c291273e073cb4e1049655bea848dbc441 (patch) | |
tree | 341cb7ac4bd5915deb8fe58947b3cc352687556d /src/file_op.rs | |
parent | Reformat style.scss (diff) | |
parent | Add asynchronous directory size counting (diff) | |
download | miniserve-419204c291273e073cb4e1049655bea848dbc441.tar.gz miniserve-419204c291273e073cb4e1049655bea848dbc441.zip |
Merge pull request #1482 from svenstaro/add-asynchronous-directory-size-loading
Add asynchronous directory size counting
Diffstat (limited to 'src/file_op.rs')
-rw-r--r-- | src/file_op.rs | 34 |
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()) })?; |