处理临时文件
This commit is contained in:
@@ -1210,8 +1210,8 @@ fn scan_upgrade_dir(app_name: &str) -> Vec<(String, PathBuf)> {
|
||||
files
|
||||
}
|
||||
|
||||
/// 扫描本地升级目录,返回 .tmp 文件列表(相对路径)
|
||||
fn scan_local_tmp_files(app_name: &str) -> Vec<String> {
|
||||
/// 扫描本地升级目录,返回 .tmp 文件列表(正式文件名 + 大小)
|
||||
fn scan_local_tmp_files(app_name: &str) -> Vec<(String, u64)> {
|
||||
let upgrade_base = get_updater_data_dir()
|
||||
.join("Updater")
|
||||
.join("UpGrade")
|
||||
@@ -1241,7 +1241,10 @@ fn scan_local_tmp_files(app_name: &str) -> Vec<String> {
|
||||
// 去掉 .tmp 后缀,发送正式文件名
|
||||
let official_name = rel_str.strip_suffix(".tmp")
|
||||
.unwrap_or(&rel_str);
|
||||
tmp_files.push(official_name.to_string());
|
||||
// 获取文件大小
|
||||
if let Ok(metadata) = fs::metadata(&path) {
|
||||
tmp_files.push((official_name.to_string(), metadata.len()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1257,13 +1260,20 @@ fn scan_local_tmp_files(app_name: &str) -> Vec<String> {
|
||||
fn send_get_all_file(
|
||||
sender: &cube_lib::websocket::MessageSender,
|
||||
app_name: &str,
|
||||
tmp_files: &[String],
|
||||
tmp_files: &[(String, u64)],
|
||||
) {
|
||||
let ts = chrono::Local::now().format("%Y-%m-%d %H:%M:%S%.3f");
|
||||
let tmp_files_json = serde_json::to_string(tmp_files).unwrap_or_else(|_| "[]".to_string());
|
||||
// 构造成 {filename, size} 格式的数组
|
||||
let tmp_files_json: Vec<serde_json::Value> = tmp_files.iter()
|
||||
.map(|(name, size)| serde_json::json!({
|
||||
"filename": name,
|
||||
"size": size
|
||||
}))
|
||||
.collect();
|
||||
let tmp_files_str = serde_json::to_string(&tmp_files_json).unwrap_or_else(|_| "[]".to_string());
|
||||
let msg_str = format!(
|
||||
r#"{{"Type":"GetAllFile","Data":{{"app_name":"{}","tmp_files":{}}}}}"#,
|
||||
app_name, tmp_files_json
|
||||
app_name, tmp_files_str
|
||||
);
|
||||
log_print!("{} 发送消息:{}", ts, msg_str);
|
||||
sender.send(msg_str);
|
||||
@@ -1673,7 +1683,7 @@ async fn run_updater(debug_mode: bool) -> bool {
|
||||
.unwrap_or_default();
|
||||
|
||||
// 获取服务端临时文件列表
|
||||
let server_tmp_files: Vec<(String, Option<u64>, Option<String>)> = allfile_data
|
||||
let _server_tmp_files: Vec<(String, Option<u64>, Option<String>)> = allfile_data
|
||||
.get("tmp_files")
|
||||
.and_then(|v| v.as_array())
|
||||
.map(|arr| {
|
||||
@@ -1696,84 +1706,90 @@ async fn run_updater(debug_mode: bool) -> bool {
|
||||
.join("UpGrade")
|
||||
.join(app_name);
|
||||
|
||||
// 1. 扫描本地文件
|
||||
// 1. 扫描本地文件(分别记录正式文件和 tmp 文件)
|
||||
let mut local_files: std::collections::HashSet<String> = std::collections::HashSet::new();
|
||||
#[allow(dead_code)]
|
||||
let mut local_tmp_files: std::collections::HashSet<String> = std::collections::HashSet::new();
|
||||
if upgrade_base.exists() {
|
||||
if let Ok(entries) = fs::read_dir(&upgrade_base) {
|
||||
for entry in entries.flatten() {
|
||||
let path = entry.path();
|
||||
if path.is_file() {
|
||||
if let Some(name) = path.file_name().and_then(|n| n.to_str()) {
|
||||
local_files.insert(name.to_string());
|
||||
if name.ends_with(".tmp") {
|
||||
// tmp 文件:去掉 .tmp 后缀存储
|
||||
let official_name = name.trim_end_matches(".tmp");
|
||||
local_tmp_files.insert(official_name.to_string());
|
||||
} else {
|
||||
local_files.insert(name.to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 以服务端为准,删除本地多余文件
|
||||
let server_filenames: std::collections::HashSet<String> = server_files
|
||||
// 2. 以服务端为准,删除本地多余的正式文件和临时文件
|
||||
let server_official_names: std::collections::HashSet<String> = server_files
|
||||
.iter()
|
||||
.map(|(name, _, _)| name.clone())
|
||||
.chain(server_tmp_files.iter().map(|(name, _, _)| name.clone()))
|
||||
.collect();
|
||||
|
||||
for local_file in &local_files {
|
||||
if !server_filenames.contains(local_file) {
|
||||
if !server_official_names.contains(local_file) {
|
||||
// 删除本地正式文件
|
||||
let file_path = upgrade_base.join(local_file);
|
||||
if file_path.exists() {
|
||||
log_print!("{} [AllFile] 删除多余文件: {}", ts, local_file);
|
||||
log_print!("{} [AllFile] 删除多余正式文件: {}", ts, local_file);
|
||||
let _ = fs::remove_file(&file_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 处理临时文件(MD5 不一致则删除)
|
||||
for (tmp_filename, _, server_md5) in &server_tmp_files {
|
||||
let tmp_path = upgrade_base.join(tmp_filename);
|
||||
if tmp_path.exists() {
|
||||
if let Some(sm) = server_md5 {
|
||||
// 计算本地 tmp 文件的 md5(全文件)
|
||||
let local_md5 = compute_file_md5(&tmp_path);
|
||||
if let Some(lm) = local_md5 {
|
||||
if &lm != sm {
|
||||
log_print!("{} [AllFile] tmp {} MD5不一致 (本地={}, 服务端={}),删除", ts, tmp_filename, lm, sm);
|
||||
let _ = fs::remove_file(&tmp_path);
|
||||
} else {
|
||||
log_print!("{} [AllFile] tmp {} MD5一致,跳过", ts, tmp_filename);
|
||||
}
|
||||
}
|
||||
// 同时删除对应的临时文件(如有)
|
||||
let tmp_file_with_ext = format!("{}.tmp", local_file);
|
||||
let tmp_path = upgrade_base.join(&tmp_file_with_ext);
|
||||
if tmp_path.exists() {
|
||||
log_print!("{} [AllFile] 删除多余临时文件: {}", ts, tmp_file_with_ext);
|
||||
let _ = fs::remove_file(&tmp_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 4. 处理正式文件(MD5 不一致则创建空 tmp 文件)
|
||||
// 3. 处理服务端文件列表:比较 MD5,决定如何处理
|
||||
for (filename, _, server_md5) in &server_files {
|
||||
let file_path = upgrade_base.join(filename);
|
||||
let tmp_filename = format!("{}.tmp", filename);
|
||||
let tmp_path = upgrade_base.join(&tmp_filename);
|
||||
let has_tmp = tmp_path.exists();
|
||||
let has_official = file_path.exists();
|
||||
|
||||
// 检查是否已有有效的 tmp 文件
|
||||
if tmp_path.exists() {
|
||||
// tmp 已存在,由后续 Md5 响应处理
|
||||
continue;
|
||||
}
|
||||
|
||||
// 检查正式文件是否存在
|
||||
if file_path.exists() {
|
||||
// 计算本地文件的 md5
|
||||
if has_tmp {
|
||||
// 情况A:本地有临时文件 → 比较临时文件
|
||||
let local_md5 = compute_file_md5(&tmp_path);
|
||||
if let Some(lm) = local_md5 {
|
||||
if &lm != server_md5 {
|
||||
// MD5 不对 → 清空临时文件内容
|
||||
log_print!("{} [AllFile] tmp {} MD5不一致 (本地={}, 服务端={}),清空", ts, tmp_filename, lm, server_md5);
|
||||
if let Ok(file) = fs::File::create(&tmp_path) {
|
||||
let _ = file.set_len(0);
|
||||
}
|
||||
// 发送下载请求
|
||||
request_download_for_app(&sender, &app_name, filename, 0);
|
||||
update_performed_clone2.store(true, std::sync::atomic::Ordering::SeqCst);
|
||||
} else {
|
||||
log_print!("{} [AllFile] tmp {} MD5一致,续传", ts, tmp_filename);
|
||||
}
|
||||
}
|
||||
} else if has_official {
|
||||
// 情况B:本地没有临时文件但有正式文件 → 比较正式文件
|
||||
let local_md5 = compute_file_md5(&file_path);
|
||||
if let Some(ref lm) = local_md5 {
|
||||
if lm != server_md5 {
|
||||
if let Some(lm) = local_md5 {
|
||||
if &lm != server_md5 {
|
||||
// MD5 不对 → 创建空的临时文件
|
||||
log_print!("{} [AllFile] {} MD5不一致 (本地={}, 服务端={}),创建 tmp", ts, filename, lm, server_md5);
|
||||
// 先创建文件的父目录
|
||||
if let Some(parent) = tmp_path.parent() {
|
||||
let _ = fs::create_dir_all(parent);
|
||||
}
|
||||
// 创建空 tmp 文件标记需要下载
|
||||
if let Ok(_) = File::create(&tmp_path) {
|
||||
log_print!("{} [AllFile] 创建空 tmp 文件: {}", ts, tmp_filename);
|
||||
// 为这个正式文件发送下载请求
|
||||
request_download_for_app(&sender, &app_name, filename, 0);
|
||||
update_performed_clone2.store(true, std::sync::atomic::Ordering::SeqCst);
|
||||
}
|
||||
@@ -1782,35 +1798,28 @@ async fn run_updater(debug_mode: bool) -> bool {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 文件不存在,创建空 tmp
|
||||
// 情况C:本地连正式文件都没有 → 直接创建空的临时文件
|
||||
log_print!("{} [AllFile] {} 不存在,创建 tmp", ts, filename);
|
||||
// 先创建文件的父目录
|
||||
if let Some(parent) = tmp_path.parent() {
|
||||
let _ = fs::create_dir_all(parent);
|
||||
}
|
||||
if let Ok(_) = File::create(&tmp_path) {
|
||||
log_print!("{} [AllFile] 创建空 tmp 文件: {}", ts, tmp_filename);
|
||||
// 为这个正式文件发送下载请求(函数内部会记录发送消息日志)
|
||||
request_download_for_app(&sender, &app_name, filename, 0);
|
||||
update_performed_clone2.store(true, std::sync::atomic::Ordering::SeqCst);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 5. 发送下载请求(处理服务端返回的 tmp 文件)
|
||||
for (tmp_filename, _, _server_md5) in &server_tmp_files {
|
||||
let tmp_path = upgrade_base.join(tmp_filename);
|
||||
let original_filename = tmp_filename.trim_end_matches(".tmp");
|
||||
|
||||
// 4. 为剩余的有效临时文件发送续传请求
|
||||
for (filename, _, _) in &server_files {
|
||||
let tmp_filename = format!("{}.tmp", filename);
|
||||
let tmp_path = upgrade_base.join(&tmp_filename);
|
||||
if tmp_path.exists() {
|
||||
// tmp 存在,发送请求续传
|
||||
// tmp 存在,发送续传请求
|
||||
let file_size = fs::metadata(&tmp_path).map(|m| m.len()).unwrap_or(0);
|
||||
request_download_for_app(&sender, &app_name, original_filename, file_size);
|
||||
} else {
|
||||
// tmp 不存在,重新下载
|
||||
request_download_for_app(&sender, &app_name, original_filename, 0);
|
||||
request_download_for_app(&sender, &app_name, filename, file_size);
|
||||
}
|
||||
update_performed_clone2.store(true, std::sync::atomic::Ordering::SeqCst);
|
||||
}
|
||||
|
||||
// 6. 检查是否所有应用都处理完成
|
||||
|
||||
Reference in New Issue
Block a user