1 use std::{ 2 fs::File, 3 path::Path, 4 process::{Command, Stdio}, 5 }; 6 7 use reqwest::{blocking::ClientBuilder, Url}; 8 9 use super::stdio::StdioUtils; 10 11 pub struct FileUtils; 12 13 impl FileUtils { 14 ///从指定url下载文件到指定路径 15 pub fn download_file(url: &str, path: &Path) -> Result<(), Box<dyn std::error::Error>> { 16 let tempurl = Url::parse(url).expect("failed to parse the url"); 17 let file_name = tempurl 18 .path_segments() 19 .expect("connot be base url") 20 .last() 21 .expect("failed to get the filename from the url"); 22 let client = ClientBuilder::new() 23 .timeout(std::time::Duration::from_secs(10)) 24 .build()?; 25 let mut response = client.get(url).send()?; 26 let mut file = File::create(path.join(file_name))?; 27 response.copy_to(&mut file)?; 28 Ok(()) 29 } 30 31 /// 把指定路径下所有文件和文件夹递归地移动到另一个文件中 32 pub fn move_files(src: &Path, dst: &Path) -> std::io::Result<()> { 33 for entry in src.read_dir()? { 34 let entry = entry?; 35 let path = entry.path(); 36 let new_path = dst.join(path.file_name().unwrap()); 37 if entry.file_type()?.is_dir() { 38 std::fs::create_dir_all(&new_path)?; 39 FileUtils::move_files(&path, &new_path)?; 40 } else { 41 std::fs::rename(&path, &new_path)?; 42 } 43 } 44 Ok(()) 45 } 46 47 /// 递归地复制给定目录下所有文件到另一个文件夹中 48 pub fn copy_dir_all(src: &Path, dst: &Path) -> Result<(), String> { 49 log::trace!("FileUtils::copy_dir_all: src: {:?}, dst: {:?}", src, dst); 50 let mut cmd = Command::new("cp"); 51 cmd.arg("-r").arg("-f").arg("./").arg(dst); 52 53 cmd.current_dir(src); 54 55 // 创建子进程,执行命令 56 let proc: std::process::Child = cmd 57 .stderr(Stdio::piped()) 58 .spawn() 59 .map_err(|e| e.to_string())?; 60 let output = proc.wait_with_output().map_err(|e| e.to_string())?; 61 62 if !output.status.success() { 63 return Err(format!( 64 "copy_dir_all failed, status: {:?}, stderr: {:?}", 65 output.status, 66 StdioUtils::tail_n_str(StdioUtils::stderr_to_lines(&output.stderr), 5) 67 )); 68 } 69 Ok(()) 70 } 71 } 72