mod login; mod update; use clap::Parser; use login::login_and_get_token; use update::{upload_file_with_progress, UploadProgress}; use std::process; #[derive(Parser)] #[command(name = "upfs")] #[command(about = "Upload file to UPFS server")] struct Cli { /// File path to upload #[arg(short, long)] file: String, /// Remote file path on server #[arg(short, long)] remote_path: String, /// Username for authentication #[arg(short, long, default_value = "admin")] username: String, /// Password for authentication #[arg(short, long)] password: Option, } #[tokio::main] async fn main() { let cli = Cli::parse(); // 检查文件是否存在 if !std::path::Path::new(&cli.file).exists() { eprintln!("错误: 文件 '{}' 不存在", cli.file); process::exit(1); } // 获取密码(如果没有提供则询问) let password = match cli.password { Some(pwd) => pwd, None => { println!("请输入密码:"); let mut input = String::new(); std::io::stdin().read_line(&mut input).expect("读取密码失败"); input.trim().to_string() } }; println!("正在登录服务器..."); // 登录获取token let token = match login_and_get_token(cli.username, password).await { Ok(token) => { println!("登录成功!"); token } Err(e) => { eprintln!("登录失败: {}", e); process::exit(1); } }; println!("正在上传文件: {} 到远程路径: {}", cli.file, cli.remote_path); println!("进度条说明: [进度百分比] | 上传速度 | 已用时间 | 剩余时间 | 已上传/总大小"); println!(); // 默认使用进度跟踪的上传 match upload_file_with_progress(token, &cli.file, &cli.remote_path, |progress| { print_progress(&progress); }).await { Ok(response) => { println!("\n✅ 文件上传成功!"); println!("服务器响应: {}", response.text); } Err(e) => { eprintln!("\n上传过程中发生错误: {}", e); process::exit(1); } } } // 显示进度的函数 fn print_progress(progress: &UploadProgress) { print!("\r\x1b[K"); // 清除从光标到行尾的内容 print!("["); let bar_width = 30; let filled = (progress.percentage / 100.0 * bar_width as f64) as usize; for i in 0..bar_width { if i < filled { print!("="); } else if i == filled { print!(">"); } else { print!(" "); } } print!("] {:.1}% | {} | {} | {}", progress.percentage, progress.format_speed(), progress.format_elapsed_time(), progress.format_remaining_time() ); print!(" | {}/{}", format_bytes(progress.bytes_uploaded), progress.format_bytes() ); std::io::Write::flush(&mut std::io::stdout()).unwrap(); } fn format_bytes(bytes: u64) -> String { if bytes < 1024 { format!("{} B", bytes) } else if bytes < 1024 * 1024 { format!("{:.2} KB", bytes as f64 / 1024.0) } else if bytes < 1024 * 1024 * 1024 { format!("{:.2} MB", bytes as f64 / (1024.0 * 1024.0)) } else { format!("{:.2} GB", bytes as f64 / (1024.0 * 1024.0 * 1024.0)) } }