mirror of
https://github.com/clash-verge-rev/clash-verge-rev
synced 2025-05-05 06:33:45 +08:00
feat: add icon file content check to prevent saving failed downloads
This commit is contained in:
parent
9f2c4b4f35
commit
cd6eb26a41
@ -90,42 +90,62 @@ pub async fn download_icon_cache(url: String, name: String) -> CmdResult<String>
|
|||||||
let temp_path = icon_cache_dir.join(format!("{}.downloading", &name));
|
let temp_path = icon_cache_dir.join(format!("{}.downloading", &name));
|
||||||
|
|
||||||
// 下载文件到临时位置
|
// 下载文件到临时位置
|
||||||
let response = wrap_err!(reqwest::get(url).await)?;
|
let response = wrap_err!(reqwest::get(&url).await)?;
|
||||||
|
|
||||||
|
// 检查内容类型是否为图片
|
||||||
|
let content_type = response.headers()
|
||||||
|
.get(reqwest::header::CONTENT_TYPE)
|
||||||
|
.and_then(|v| v.to_str().ok())
|
||||||
|
.unwrap_or("");
|
||||||
|
|
||||||
|
let is_image = content_type.starts_with("image/");
|
||||||
|
|
||||||
|
// 获取响应内容
|
||||||
let content = wrap_err!(response.bytes().await)?;
|
let content = wrap_err!(response.bytes().await)?;
|
||||||
|
|
||||||
// 写入临时文件
|
// 检查内容是否为HTML (针对CDN错误页面)
|
||||||
{
|
let is_html = content.len() > 15 &&
|
||||||
let mut file = match std::fs::File::create(&temp_path) {
|
(content.starts_with(b"<!DOCTYPE html") ||
|
||||||
Ok(file) => file,
|
content.starts_with(b"<html") ||
|
||||||
Err(_) => {
|
content.starts_with(b"<?xml"));
|
||||||
if icon_path.exists() {
|
|
||||||
return Ok(icon_path.to_string_lossy().to_string());
|
|
||||||
} else {
|
|
||||||
return Err("Failed to create temporary file".into());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
wrap_err!(std::io::copy(&mut content.as_ref(), &mut file))?;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 再次检查目标文件是否已存在,避免重命名覆盖其他线程已完成的文件
|
// 只有当内容确实是图片时才保存
|
||||||
if !icon_path.exists() {
|
if is_image && !is_html {
|
||||||
// 使用原子重命名操作将临时文件移动到最终位置
|
{
|
||||||
match std::fs::rename(&temp_path, &icon_path) {
|
let mut file = match std::fs::File::create(&temp_path) {
|
||||||
Ok(_) => {},
|
Ok(file) => file,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
let _ = std::fs::remove_file(&temp_path);
|
if icon_path.exists() {
|
||||||
if icon_path.exists() {
|
return Ok(icon_path.to_string_lossy().to_string());
|
||||||
return Ok(icon_path.to_string_lossy().to_string());
|
} else {
|
||||||
|
return Err("Failed to create temporary file".into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
wrap_err!(std::io::copy(&mut content.as_ref(), &mut file))?;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 再次检查目标文件是否已存在,避免重命名覆盖其他线程已完成的文件
|
||||||
|
if !icon_path.exists() {
|
||||||
|
match std::fs::rename(&temp_path, &icon_path) {
|
||||||
|
Ok(_) => {},
|
||||||
|
Err(_) => {
|
||||||
|
let _ = std::fs::remove_file(&temp_path);
|
||||||
|
if icon_path.exists() {
|
||||||
|
return Ok(icon_path.to_string_lossy().to_string());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
let _ = std::fs::remove_file(&temp_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(icon_path.to_string_lossy().to_string())
|
||||||
} else {
|
} else {
|
||||||
let _ = std::fs::remove_file(&temp_path);
|
let _ = std::fs::remove_file(&temp_path);
|
||||||
|
Err(format!("下载的内容不是有效图片: {}", url).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(icon_path.to_string_lossy().to_string())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user