From 0e0ce22bc0a29d0f717af584dd235856a0a03f00 Mon Sep 17 00:00:00 2001 From: Jia Chao Date: Fri, 5 Jul 2024 14:13:44 +0800 Subject: [PATCH] =?UTF-8?q?file:=20=E5=A2=9E=E5=8A=A0=20temp=5Fdir=20?= =?UTF-8?q?=E5=92=8C=20walk=5Fdir?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jia Chao --- src/file.rs | 86 +++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 81 insertions(+), 5 deletions(-) diff --git a/src/file.rs b/src/file.rs index 938ee45..5a16592 100644 --- a/src/file.rs +++ b/src/file.rs @@ -1,13 +1,89 @@ +use std::env; +use std::fs; use std::path::{Path, PathBuf}; + use tokio::fs::{File, OpenOptions}; use tokio::io::{AsyncSeekExt, AsyncWriteExt, SeekFrom}; - use futures_util::StreamExt; use indicatif::{ProgressBar, ProgressStyle}; use path_absolutize::Absolutize; use reqwest::Client; use tracing::{debug, info}; +use crate::util::uuid; + +/// 返回一个临时目录路径,可指定是否立即创建其路径。 +/// +/// 该函数生成一个基于系统临时目录的新目录路径,并根据 `create` 参数决定是否创建该目录。 +/// 生成的路径包含一个唯一标识符,以确保每次调用都生成不同的目录。 +/// +/// # 参数 +/// - `create`: 一个布尔值,如果为 `true`,则创建目录。 +/// +/// # 返回值 +/// 返回一个包含生成路径的 `Result` 类型。如果 `create` 为 `true` 且目录创建失败,则返回错误信息。 +/// +/// # 示例 +/// ```rust +/// let temp_dir_path = temp_dir(true)?; +/// println!("Temporary directory path: {:?}", temp_dir_path); +/// ``` +pub fn temp_dir(create: bool) -> crate::Result { + // 获取系统临时目录路径并添加一个唯一标识符 + let mut path = PathBuf::from(env::temp_dir()); + path.push(uuid()); + // 如果 `create` 为 `true`,则创建该目录 + if create { + fs::create_dir(&path)?; + debug!("create temp_dir: {}", &path.to_str().unwrap()); + } + // 返回生成的路径 + Ok(path) +} + +/// 遍历目录并返回包含所有文件路径的向量。 +/// +/// 该函数递归遍历给定路径下的所有文件和目录,并将其路径存储在一个向量中返回。 +/// 如果 `nodir` 参数为 `true`,则不会将目录路径添加到结果中。 +/// +/// # 参数 +/// - `path`: 要遍历的目录路径。 +/// - `nodir`: 一个布尔值,如果为 `true`,则不会将目录路径添加到结果中。 +/// +/// # 返回值 +/// 返回一个包含所有文件和(可选)目录路径的向量。 +/// +/// # 示例 +/// ```rust +/// let files = walk_dir("/path/to/dir", true); +/// for file in files { +/// println!("{:?}", file); +/// } +/// ``` +pub fn walk_dir>(path: P, nodir: bool) -> Vec { + // 创建一个存储结果的向量 + let mut res = vec![]; + // 遍历给定路径下的所有条目 + for entry in std::fs::read_dir(path).expect("read_dir call failed!") { + // 获取条目的路径 + let entry = entry.unwrap().path(); + // 如果条目是目录 + if entry.is_dir() { + // 如果 `nodir` 为 `false`,则将目录路径添加到结果中 + if !nodir { + res.push(entry.clone()); + } + // 递归遍历目录并将结果添加到当前结果中 + res.append(&mut walk_dir(entry, nodir)); + } else { + // 如果条目是文件,则将其路径添加到结果中 + res.push(entry); + } + } + // 返回包含所有文件和(可选)目录路径的向量 + res +} + /// 从给定的 URL 下载文件并将其保存到指定的目标路径。 /// /// 该函数初始化一个异步运行时,并阻塞在异步下载函数上,直到下载完成。 @@ -31,7 +107,7 @@ use tracing::{debug, info}; /// /// # 备注 /// `crate::async_runtime` 函数是一个辅助函数,用于返回一个异步运行时的引用。`async_download` 函数是执行实际异步下载过程的实现。 -pub fn download>(url: &str, target: Option

) -> crate::Result<()> { +pub fn download>(url: String, target: Option

) -> crate::Result<()> { // 使用库中的辅助函数初始化异步运行时。 let rt = crate::async_runtime()?; // 阻塞在异步下载函数上,直到下载完成。 @@ -63,12 +139,12 @@ pub fn download>(url: &str, target: Option

) -> crate::Result<( /// /// # 备注 /// 使用 `Client` 进行 HTTP 请求,`OpenOptions` 和 `File` 进行文件操作,支持断点续传。 -pub async fn async_download>(url: &str, target: Option

) -> crate::Result<()> { +pub async fn async_download>(url: String, target: Option

) -> crate::Result<()> { debug!("Download url: {}", url); // 创建一个新的 HTTP 客户端 let client = Client::new(); // 发送 GET 请求获取响应 - let response = client.get(url).send().await?; + let response = client.get(url.clone()).send().await?; // 确定下载文件的路径 let download_file = match target { @@ -82,7 +158,7 @@ pub async fn async_download>(url: &str, target: Option

) -> cra } None => { // 如果未指定目标路径,则使用 URL 的文件名 - let _remote = Path::new(url); + let _remote = Path::new(&url); let _local = match _remote.file_name() { Some(file) => file, None => return Err("无效的文件名!".into()),