use std::fs;
use std::fs::File;
use std::io::{Write};
use std::path::PathBuf;
use futures::StreamExt;
use md5::{Digest, Md5};
use reqwest::Url;
pub(crate) async fn download_file_with_integrity(url: &str, file_path: &str, md5_expected: &str) -> Result<(), Box<dyn std::error::Error>> {
let url = Url::parse(url)?;
let response = reqwest::get(url).await?;
if ! response.status().is_success() {
return Err(format!("Bad HTTP status code: {}", response.status().as_str()).into());
}
let mut file = File::create(&file_path)?;
let mut hasher = Md5::new();
let mut download_stream = response.bytes_stream();
while let Some(chunk_result) = download_stream.next().await {
let chunk = chunk_result?;
hasher.update(&chunk);
file.write_all(&chunk)?;
}
let result = hasher.finalize();
let md5_hex_value = format!("{:x}", result);
if md5_hex_value != md5_expected {
if let Err(e) = fs::remove_file(&file_path) {
eprintln!("Failed to remove file: {}", e);
}
return Err("MD5 hash mismatch".into());
}
Ok(())
}
pub(crate) fn get_or_create_home_dir_sub_folder(sub_folder: &str) -> PathBuf {
let model_folder = if let Some(mut home_dir) = dirs::home_dir() {
home_dir.push(sub_folder);
home_dir
} else {
PathBuf::from("./")
};
if ! model_folder.exists() {
if let Err(err) = fs::create_dir_all(&model_folder) {
eprintln!("Failed to create model folder: {}", err);
}
}
model_folder
}