Explorar o código

fix: 文件大小解析的bug && 不显示上一级页面的bug

Signed-off-by: longjin <longjin@DragonOS.org>
longjin hai 1 semana
pai
achega
2d5d729e13
Modificáronse 4 ficheiros con 107 adicións e 10 borrados
  1. 19 9
      src/render/mod.rs
  2. 1 0
      src/storage/mod.rs
  3. 3 1
      src/storage/nginx.rs
  4. 84 0
      src/storage/utils.rs

+ 19 - 9
src/render/mod.rs

@@ -29,6 +29,17 @@ pub struct IndexDirEntry {
     pub size: String,
 }
 
+impl IndexDirEntry {
+    fn parent_entry() -> IndexDirEntry {
+        Self {
+            name: "../".to_string(),
+            url: "../".to_string(),
+            modified: "".to_string(),
+            size: "".to_string(),
+        }
+    }
+}
+
 impl From<StorageEntry> for IndexDirEntry {
     fn from(entry: StorageEntry) -> Self {
         Self {
@@ -62,16 +73,15 @@ fn format_size(size: Option<usize>) -> String {
 pub fn render_list(
     base_path: &str,
     req_path: &str,
-    entries: Vec<StorageEntry>,
+    src_entries: Vec<StorageEntry>,
 ) -> anyhow::Result<String> {
-    let entries: Vec<IndexDirEntry> = entries
-        .into_iter()
-        .map(|e| {
-            let mut et: IndexDirEntry = e.into();
-            et.url = format!("{}/{}", base_path, et.url);
-            et
-        })
-        .collect();
+    let mut entries = Vec::new();
+    entries.push(IndexDirEntry::parent_entry());
+    src_entries.into_iter().for_each(|e| {
+        let mut et: IndexDirEntry = e.into();
+        et.url = format!("{}/{}", base_path, et.url);
+        entries.push(et);
+    });
 
     let template = AutoIndexTemplate {
         path: req_path.to_string(),

+ 1 - 0
src/storage/mod.rs

@@ -6,6 +6,7 @@ use async_trait::async_trait;
 
 pub mod local;
 pub mod nginx;
+mod utils;
 
 lazy_static! {
     static ref STORAGE_PROVIDER: Arc<dyn StorageProvider> = {

+ 3 - 1
src/storage/nginx.rs

@@ -6,6 +6,8 @@ use reqwest::Url;
 use scraper::{Html, Selector};
 use url::Url as UrlParser;
 
+use crate::storage::utils::parse_file_size;
+
 use super::{StorageEntry, StorageProvider};
 
 pub struct NginxStorageProvider {
@@ -108,7 +110,7 @@ impl NginxStorageProvider {
                                     );
 
                             // 尝试解析文件大小
-                            let size = parts[3].parse::<usize>().ok();
+                            let size = parse_file_size(parts[3]);
 
                             (modified, size)
                         } else {

+ 84 - 0
src/storage/utils.rs

@@ -0,0 +1,84 @@
+/// Parses a human-readable file size (e.g., "1", "1B", "10M", "1.3G") into bytes.
+pub(super) fn parse_file_size(size_str: &str) -> Option<usize> {
+    let size_str = size_str.trim().to_uppercase();
+    if size_str.is_empty() {
+        return None;
+    }
+
+    // Check if the string ends with a unit (B, K, M, G, T)
+    let (num_part, unit) = if size_str.ends_with('B') {
+        (&size_str[..size_str.len() - 1], 'B')
+    } else if let Some(last_char) = size_str.chars().last() {
+        if last_char.is_alphabetic() {
+            (&size_str[..size_str.len() - 1], last_char)
+        } else {
+            (size_str.as_str(), 'B') // Default to bytes if no unit
+        }
+    } else {
+        (size_str.as_str(), 'B')
+    };
+
+    // Parse the numeric part
+    let num = num_part.parse::<f64>().ok()?;
+    if num < 0.0 {
+        return None;
+    }
+
+    // Calculate bytes based on the unit
+    let multiplier: usize = match unit {
+        'B' => 1,
+        'K' => 1024,
+        'M' => 1024 * 1024,
+        'G' => 1024 * 1024 * 1024,
+        'T' => 1024 * 1024 * 1024 * 1024,
+        _ => return None, // Unknown unit
+    };
+
+    Some((num * multiplier as f64) as usize)
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn test_parse_file_size_valid() {
+        // Test cases with valid inputs
+        assert_eq!(parse_file_size("1"), Some(1));
+        assert_eq!(parse_file_size("1B"), Some(1));
+        assert_eq!(parse_file_size("10K"), Some(10 * 1024));
+        assert_eq!(
+            parse_file_size("2.5M"),
+            Some((2.5 * 1024.0 * 1024.0) as usize)
+        );
+        assert_eq!(parse_file_size("1G"), Some(1024 * 1024 * 1024));
+        assert_eq!(
+            parse_file_size("0.5T"),
+            Some((0.5 * 1024.0 * 1024.0 * 1024.0 * 1024.0) as usize)
+        );
+        assert_eq!(parse_file_size(" 123  "), Some(123)); // Test trimming
+        assert_eq!(parse_file_size("1k"), Some(1024)); // Case-insensitive
+        assert_eq!(parse_file_size("1m"), Some(1024 * 1024)); // Case-insensitive
+    }
+
+    #[test]
+    fn test_parse_file_size_invalid() {
+        // Test cases with invalid inputs
+        assert_eq!(parse_file_size(""), None); // Empty string
+        assert_eq!(parse_file_size("ABC"), None); // Non-numeric
+        assert_eq!(parse_file_size("1.2.3"), None); // Invalid numeric format
+        assert_eq!(parse_file_size("1X"), None); // Unknown unit
+        assert_eq!(parse_file_size("-1"), None); // Negative number (if not supported)
+    }
+
+    #[test]
+    fn test_parse_file_size_edge_cases() {
+        // Edge cases
+        assert_eq!(parse_file_size("0"), Some(0)); // Zero value
+        assert_eq!(parse_file_size("0B"), Some(0)); // Zero with unit
+        assert_eq!(
+            parse_file_size("999999999999T"),
+            Some((999999999999.0 * 1024.0 * 1024.0 * 1024.0 * 1024.0) as usize)
+        );
+    }
+}