use std::{error::Error, fs::File, path::Path};
use flate2::read::GzDecoder;
use futures_util::StreamExt;
use indicatif::{ProgressBar, ProgressStyle};
use reqwest::Client;
use tar::Archive;
use tokio::{fs, io::AsyncWriteExt};
pub async fn decompress_file(url: &str, target_dir: &str) -> Result<(), Box<dyn Error>> {
let tar_gz = File::open(url)?;
let decomppress = GzDecoder::new(tar_gz);
let mut archive = Archive::new(decomppress);
if !Path::new(target_dir).exists() {
fs::create_dir_all(target_dir).await?;
}
archive.unpack(target_dir)?;
Ok(())
}
pub async fn download_file(url: &str, output: &str) -> Result<(), Box<dyn Error>> {
let client = Client::new();
let res = client.get(url).send().await?;
if res.status().is_success() {
let content_size = res.content_length().ok_or("无法获取文件大小")?;
let mut file = fs::File::create(output).await?;
let pb = ProgressBar::new(content_size);
pb.set_style(
ProgressStyle::default_bar()
.template("{msg} [{elapsed_precise}] {bar:80} {percent}%")?
.progress_chars("##-"),
);
let mut downloaded = 0;
let mut stream = res.bytes_stream();
while let Some(item) = stream.next().await {
let chunk = item?;
file.write_all(&chunk).await?;
let len = chunk.len() as u64;
downloaded += len;
pb.set_position(downloaded);
}
file.flush().await?;
pb.finish_with_message("下载完成");
Ok(())
} else {
let error_message = format!("Request failed with status code: {}", res.status());
Err(Box::new(std::io::Error::new(
std::io::ErrorKind::Other,
error_message,
)))
}
}