use serde::{Deserialize, Serialize}; use std::path::Path; #[derive(Debug, Clone, Serialize, Deserialize)] pub struct FileInfo { pub filename: String, pub file_size: u64, pub file_hash: Option, pub file_path: String, pub relative_path: String, pub upload_time: String, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct FileListResponse { pub user_id: String, pub base_path: String, pub files: Vec, pub total_files: usize, pub total_size: u64, } pub fn scan_uploaded_files(user_id: &str) -> FileListResponse { let base_path = format!("/Users/accusys/Downloads/{}", user_id); let path = Path::new(&base_path); let mut files = Vec::new(); let mut total_size = 0u64; if path.exists() { scan_directory_recursive(path, path, &mut files, &mut total_size); } FileListResponse { user_id: user_id.to_string(), base_path, total_files: files.len(), total_size, files, } } fn scan_directory_recursive( base: &Path, current: &Path, files: &mut Vec, total_size: &mut u64, ) { if let Ok(entries) = std::fs::read_dir(current) { for entry in entries.flatten() { let path = entry.path(); if path.is_file() { let filename = path .file_name() .and_then(|n| n.to_str()) .unwrap_or("unknown") .to_string(); let file_size = entry.metadata().map(|m| m.len()).unwrap_or(0); let relative_path = path .strip_prefix(base) .ok() .and_then(|p| p.to_str()) .map(|s| s.to_string()) .unwrap_or_else(|| filename.clone()); let upload_time = entry .metadata() .ok() .and_then(|m| m.modified().ok()) .and_then(|t| { let duration = t.duration_since(std::time::UNIX_EPOCH).ok()?; chrono::DateTime::from_timestamp(duration.as_secs() as i64, 0) .map(|dt| dt.format("%Y-%m-%dT%H:%M:%SZ").to_string()) }) .unwrap_or_else(|| chrono::Utc::now().format("%Y-%m-%dT%H:%M:%SZ").to_string()); let file_hash = if file_size > 0 { compute_file_hash(&path).ok() } else { Some( "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" .to_string(), ) }; files.push(FileInfo { filename, file_size, file_hash, file_path: path.to_string_lossy().to_string(), relative_path, upload_time, }); *total_size += file_size; } else if path.is_dir() { scan_directory_recursive(base, &path, files, total_size); } } } } pub fn compute_file_hash(path: &Path) -> Result { use sha2::{Digest, Sha256}; use std::io::Read; let mut file = std::fs::File::open(path)?; let mut hasher = Sha256::new(); let mut buffer = [0u8; 8192]; loop { let bytes_read = file.read(&mut buffer)?; if bytes_read == 0 { break; } hasher.update(&buffer[..bytes_read]); } Ok(format!("{:x}", hasher.finalize())) }