file: 增加 temp_dir 和 walk_dir

Signed-off-by: Jia Chao <jiac13@chinaunicom.cn>
This commit is contained in:
Jia Chao 2024-07-05 14:13:44 +08:00
parent f1b2de1a97
commit 0e0ce22bc0

View File

@ -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<PathBuf> {
// 获取系统临时目录路径并添加一个唯一标识符
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<P: AsRef<Path>>(path: P, nodir: bool) -> Vec<PathBuf> {
// 创建一个存储结果的向量
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<P: AsRef<Path>>(url: &str, target: Option<P>) -> crate::Result<()> {
pub fn download<P: AsRef<Path>>(url: String, target: Option<P>) -> crate::Result<()> {
// 使用库中的辅助函数初始化异步运行时。
let rt = crate::async_runtime()?;
// 阻塞在异步下载函数上,直到下载完成。
@ -63,12 +139,12 @@ pub fn download<P: AsRef<Path>>(url: &str, target: Option<P>) -> crate::Result<(
///
/// # 备注
/// 使用 `Client` 进行 HTTP 请求,`OpenOptions` 和 `File` 进行文件操作,支持断点续传。
pub async fn async_download<P: AsRef<Path>>(url: &str, target: Option<P>) -> crate::Result<()> {
pub async fn async_download<P: AsRef<Path>>(url: String, target: Option<P>) -> 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<P: AsRef<Path>>(url: &str, target: Option<P>) -> 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()),