From 11ea8a19d1481b0660e5a2765da6e67d3e8aa72c Mon Sep 17 00:00:00 2001 From: Sven-Hendrik Haase Date: Fri, 7 Mar 2025 11:00:48 +0100 Subject: 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. --- src/file_op.rs | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) (limited to 'src/file_op.rs') 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 { + 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, payload: web::Payload, ) -> Result { - let conf = req.app_data::().unwrap(); + let conf = req.app_data::>().unwrap(); let upload_path = sanitize_path(&query.path, conf.show_hidden).ok_or_else(|| { RuntimeError::InvalidPathError("Invalid value for 'path' parameter".to_string()) })?; -- cgit v1.2.3