- Fix trailing whitespace in kex.rs and s3.rs - Add missing KexProposal import in kex_complete.rs - Auto-fix clippy warnings across all crates - All 153 tests pass
124 lines
3.6 KiB
Rust
124 lines
3.6 KiB
Rust
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<String>,
|
|
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<FileInfo>,
|
|
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<FileInfo>,
|
|
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<String, std::io::Error> {
|
|
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()))
|
|
}
|