handle_app_file_chunk 函数在创建 .tmp 文件时,使用 file_name() 提取纯文件名,导致丢失了子目录信息(如 x64/、x86/)
This commit is contained in:
@@ -6,7 +6,7 @@ use std::sync::{Arc, Mutex};
|
|||||||
/// 日志文件(Mutex 确保线程安全写入)
|
/// 日志文件(Mutex 确保线程安全写入)
|
||||||
static LOG_FILE: std::sync::Mutex<Option<std::fs::File>> = std::sync::Mutex::new(None);
|
static LOG_FILE: std::sync::Mutex<Option<std::fs::File>> = std::sync::Mutex::new(None);
|
||||||
|
|
||||||
/// 初始化日志文件(以追加方式打开)
|
/// 初始化日志文件(启动时清除当天日志,然后以追加方式打开)
|
||||||
fn init_log_file() {
|
fn init_log_file() {
|
||||||
let mut guard = LOG_FILE.lock().unwrap();
|
let mut guard = LOG_FILE.lock().unwrap();
|
||||||
if guard.is_some() {
|
if guard.is_some() {
|
||||||
@@ -23,7 +23,10 @@ fn init_log_file() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let log_name = format!("Updater_{}.log", chrono::Local::now().format("%Y%m%d"));
|
let log_name = format!("Updater_{}.log", chrono::Local::now().format("%Y%m%d"));
|
||||||
let log_path = log_dir.join(log_name);
|
let log_path = log_dir.join(&log_name);
|
||||||
|
|
||||||
|
// 启动时清除当天的日志文件
|
||||||
|
let _ = std::fs::remove_file(&log_path);
|
||||||
|
|
||||||
match std::fs::OpenOptions::new()
|
match std::fs::OpenOptions::new()
|
||||||
.create(true)
|
.create(true)
|
||||||
@@ -814,6 +817,16 @@ fn send_next_download(ctx: &Arc<UpdateContext>, sender: &cube_lib::websocket::Me
|
|||||||
request_download_for_app(sender, &app_name, &filename, offset);
|
request_download_for_app(sender, &app_name, &filename, offset);
|
||||||
} else {
|
} else {
|
||||||
*ctx.is_downloading.lock().unwrap() = false;
|
*ctx.is_downloading.lock().unwrap() = false;
|
||||||
|
|
||||||
|
// 队列为空,检查是否所有应用都处理完了
|
||||||
|
let ts = chrono::Local::now().format("%Y-%m-%d %H:%M:%S%.3f");
|
||||||
|
let pending_apps = ctx.pending_allfile_apps.lock().unwrap();
|
||||||
|
if pending_apps.is_empty() {
|
||||||
|
log_print!("{} [下载] 所有应用文件下载完成,进入 Complete 阶段", ts);
|
||||||
|
*ctx.current_phase.lock().unwrap() = UpdatePhase::Complete;
|
||||||
|
} else {
|
||||||
|
log_print!("{} [下载] 队列为空,等待 {} 个应用完成 AllFile 响应", ts, pending_apps.len());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -863,17 +876,14 @@ fn handle_app_file_chunk(
|
|||||||
}
|
}
|
||||||
app_map.remove(&key);
|
app_map.remove(&key);
|
||||||
|
|
||||||
// filename 可能含路径分隔符,取纯文件名部分
|
// relative_path 已经是去掉 app_name/ 前缀的相对路径(如 "x64/SQLite.Interop.dll")
|
||||||
let tmp_filename = std::path::Path::new(filename)
|
// 直接用它构建路径,保留子目录信息
|
||||||
.file_name()
|
|
||||||
.and_then(|n| n.to_str())
|
|
||||||
.unwrap_or(filename);
|
|
||||||
|
|
||||||
let temp_path = get_updater_data_dir()
|
let temp_path = get_updater_data_dir()
|
||||||
.join("Updater")
|
.join("Updater")
|
||||||
.join("UpGrade")
|
.join("UpGrade")
|
||||||
.join(app_name)
|
.join(app_name)
|
||||||
.join(format!("{}.tmp", tmp_filename));
|
.join(&relative_path)
|
||||||
|
.with_extension("tmp");
|
||||||
|
|
||||||
let ts = chrono::Local::now().format("%Y-%m-%d %H:%M:%S%.3f");
|
let ts = chrono::Local::now().format("%Y-%m-%d %H:%M:%S%.3f");
|
||||||
println!("{} [应用] 新文件: filename={}, tmp_path={:?}, parent_exists={}",
|
println!("{} [应用] 新文件: filename={}, tmp_path={:?}, parent_exists={}",
|
||||||
@@ -935,15 +945,8 @@ fn handle_app_file_chunk(
|
|||||||
let final_offset = app_map.get(&key).map(|s| s.offset).unwrap_or(0);
|
let final_offset = app_map.get(&key).map(|s| s.offset).unwrap_or(0);
|
||||||
|
|
||||||
if let Some(ref temp) = temp_path {
|
if let Some(ref temp) = temp_path {
|
||||||
// filename 来自服务端消息,可能含路径前缀(如 "sticker/app_config.json")
|
// final_path 是 temp_path 去掉 ".tmp" 后缀,直接在同一目录
|
||||||
// 只取纯文件名,与 DownloadComplete 处理器保持路径一致
|
let final_path = temp.with_extension(""); // 去掉 .tmp 后缀
|
||||||
let final_filename = std::path::Path::new(filename)
|
|
||||||
.file_name()
|
|
||||||
.and_then(|n| n.to_str())
|
|
||||||
.unwrap_or(filename);
|
|
||||||
// final_path 与 tmp 文件同一目录(升级目录),不是 app_data_dir
|
|
||||||
let upgrade_dir = temp.parent().unwrap();
|
|
||||||
let final_path = upgrade_dir.join(final_filename);
|
|
||||||
let _ = fs::create_dir_all(final_path.parent().unwrap());
|
let _ = fs::create_dir_all(final_path.parent().unwrap());
|
||||||
|
|
||||||
// 重命名(同步操作,Windows 上不会异步)
|
// 重命名(同步操作,Windows 上不会异步)
|
||||||
@@ -991,14 +994,8 @@ fn handle_app_download_complete(
|
|||||||
let temp_path = app_map.get(&key).and_then(|s| s.temp_path.clone());
|
let temp_path = app_map.get(&key).and_then(|s| s.temp_path.clone());
|
||||||
|
|
||||||
if let Some(ref temp) = temp_path {
|
if let Some(ref temp) = temp_path {
|
||||||
// filename 可能含路径分隔符,取纯文件名部分以避免路径重复
|
// final_path 是 temp_path 去掉 ".tmp" 后缀,直接在同一目录
|
||||||
let tmp_filename = std::path::Path::new(filename)
|
let final_path = temp.with_extension(""); // 去掉 .tmp 后缀
|
||||||
.file_name()
|
|
||||||
.and_then(|n| n.to_str())
|
|
||||||
.unwrap_or(filename);
|
|
||||||
// final_path 与 tmp 文件同一目录(升级目录),与 handle_app_file_chunk 的 is_last 块保持一致
|
|
||||||
let upgrade_dir = temp.parent().unwrap();
|
|
||||||
let final_path = upgrade_dir.join(tmp_filename);
|
|
||||||
let _ = fs::create_dir_all(final_path.parent().unwrap());
|
let _ = fs::create_dir_all(final_path.parent().unwrap());
|
||||||
|
|
||||||
if let Err(e) = fs::rename(temp, &final_path) {
|
if let Err(e) = fs::rename(temp, &final_path) {
|
||||||
@@ -1928,6 +1925,11 @@ async fn run_updater(debug_mode: bool) -> bool {
|
|||||||
let file_size = data_obj.get("file_size").and_then(|v| v.as_u64()).unwrap_or(0);
|
let file_size = data_obj.get("file_size").and_then(|v| v.as_u64()).unwrap_or(0);
|
||||||
let chunk_size = 4096u64;
|
let chunk_size = 4096u64;
|
||||||
|
|
||||||
|
// 调试:打印队列状态
|
||||||
|
let queue_len = ctx_clone.download_queue.lock().unwrap().len();
|
||||||
|
let ts = chrono::Local::now().format("%Y-%m-%d %H:%M:%S%.3f");
|
||||||
|
log_print!("{} [FileChunk] is_last={}, queue_len={}", ts, is_last, queue_len);
|
||||||
|
|
||||||
let candidates = ctx_clone.candidates.lock().unwrap().clone();
|
let candidates = ctx_clone.candidates.lock().unwrap().clone();
|
||||||
for (app_name, _) in &candidates {
|
for (app_name, _) in &candidates {
|
||||||
let result = handle_app_file_chunk(&ctx_clone, app_name, data_obj, debug_msg);
|
let result = handle_app_file_chunk(&ctx_clone, app_name, data_obj, debug_msg);
|
||||||
@@ -1939,6 +1941,7 @@ async fn run_updater(debug_mode: bool) -> bool {
|
|||||||
println!("{} [应用] {} / {} 下载完成", ts, app_name, filename);
|
println!("{} [应用] {} / {} 下载完成", ts, app_name, filename);
|
||||||
}
|
}
|
||||||
ctx_clone.app_completed_set.lock().unwrap().insert(format!("{}/{}", app_name, filename));
|
ctx_clone.app_completed_set.lock().unwrap().insert(format!("{}/{}", app_name, filename));
|
||||||
|
log_print!("{} [FileChunk] 调用 send_next_download, queue_len={}", ts, queue_len);
|
||||||
send_next_download(&ctx_clone, &sender);
|
send_next_download(&ctx_clone, &sender);
|
||||||
} else {
|
} else {
|
||||||
// 非最后一块,立即请求下一块(用 relative_path,不带 app_name/ 前缀)
|
// 非最后一块,立即请求下一块(用 relative_path,不带 app_name/ 前缀)
|
||||||
|
|||||||
Reference in New Issue
Block a user