fix(desktop): rewrite upload with blocking reqwest, remove tokio dependency

This commit is contained in:
OpenCode Bot
2026-05-24 21:37:13 +08:00
parent a50824e831
commit 2255ce9c65
2 changed files with 33 additions and 53 deletions

View File

@@ -5,8 +5,7 @@ edition = "2021"
[dependencies] [dependencies]
eframe = "0.31" eframe = "0.31"
reqwest = { version = "0.12", default-features = false, features = ["rustls-tls", "multipart"] } reqwest = { version = "0.12", default-features = false, features = ["rustls-tls", "multipart", "blocking"] }
tokio = { version = "1", features = ["rt", "macros"] }
serde = { version = "1", features = ["derive"] } serde = { version = "1", features = ["derive"] }
serde_json = "1" serde_json = "1"

View File

@@ -1,15 +1,11 @@
#![windows_subsystem = "windows"] #![windows_subsystem = "windows"]
use eframe::egui; use eframe::egui;
use reqwest::multipart; use reqwest::blocking::multipart;
use std::sync::mpsc; use std::sync::mpsc;
#[derive(serde::Deserialize)] #[derive(serde::Deserialize)]
struct UploadResponse { struct UploadResponse {
#[allow(dead_code)]
id: Option<String>,
#[allow(dead_code)]
filename: Option<String>,
share_url: Option<String>, share_url: Option<String>,
error: Option<String>, error: Option<String>,
} }
@@ -43,27 +39,9 @@ impl App {
self.upload_rx = Some(rx); self.upload_rx = Some(rx);
self.uploading = true; self.uploading = true;
let filename = filepath
.file_name()
.unwrap_or_default()
.to_string_lossy()
.to_string();
std::thread::spawn(move || { std::thread::spawn(move || {
let rt = tokio::runtime::Builder::new_current_thread() let result = do_upload(&api_url, &filepath);
.enable_all() let _ = tx.send(result);
.build();
match rt {
Ok(rt) => {
let result = rt.block_on(async {
do_upload(&api_url, &filepath, &filename).await
});
let _ = tx.send(result);
}
Err(e) => {
let _ = tx.send(UploadResult::Err(format!("启动运行时失败: {}", e)));
}
}
}); });
} }
@@ -87,55 +65,56 @@ impl App {
} }
} }
async fn do_upload(api_url: &str, filepath: &std::path::Path, filename: &str) -> UploadResult { fn do_upload(api_url: &str, filepath: &std::path::Path) -> UploadResult {
let filename = filepath
.file_name()
.map(|n| n.to_string_lossy().to_string())
.unwrap_or_else(|| "unknown".to_owned());
let data = match std::fs::read(filepath) { let data = match std::fs::read(filepath) {
Ok(d) => d, Ok(d) => d,
Err(e) => return UploadResult::Err(format!("读取文件失败: {}", e)), Err(e) => return UploadResult::Err(format!("读取文件失败: {}", e)),
}; };
let part = multipart::Part::bytes(data) let part = multipart::Part::bytes(data).file_name(filename);
.file_name(filename.to_owned())
.mime_str("application/octet-stream")
.unwrap_or_else(|_| multipart::Part::bytes(vec![]).file_name(filename.to_owned()));
let form = multipart::Form::new() let form = multipart::Form::new()
.part("file", part) .part("file", part)
.text("expiry", "24h"); .text("expiry", "24h");
let client = match reqwest::Client::builder().build() { let client = match reqwest::blocking::Client::builder()
.user_agent("TempFileTransfer-Desktop/0.1")
.timeout(std::time::Duration::from_secs(300))
.build()
{
Ok(c) => c, Ok(c) => c,
Err(e) => return UploadResult::Err(format!("创建客户端失败: {}", e)), Err(e) => return UploadResult::Err(format!("创建客户端失败: {}", e)),
}; };
let resp = match client.post(api_url).multipart(form).send().await { let resp = match client.post(api_url).multipart(form).send() {
Ok(r) => r, Ok(r) => r,
Err(e) => return UploadResult::Err(format!("请求失败: {}", e)), Err(e) => return UploadResult::Err(format!("网络请求失败: {}", e)),
}; };
let status = resp.status(); let status = resp.status();
let body = match resp.text().await { let body = match resp.text() {
Ok(b) => b, Ok(b) => b,
Err(e) => return UploadResult::Err(format!("读取响应失败: {}", e)), Err(e) => return UploadResult::Err(format!("读取响应失败: {}", e)),
}; };
if !status.is_success() { if !status.is_success() {
let err: UploadResponse = serde_json::from_str(&body).unwrap_or(UploadResponse { let err: UploadResponse = serde_json::from_str(&body).unwrap_or(UploadResponse {
id: None,
filename: None,
share_url: None, share_url: None,
error: Some(body), error: Some(body),
}); });
return UploadResult::Err(err.error.unwrap_or_else(|| "未知错误".to_owned())); return UploadResult::Err(err.error.unwrap_or_else(|| format!("HTTP {}", status)));
} }
let result: UploadResponse = match serde_json::from_str(&body) { match serde_json::from_str::<UploadResponse>(&body) {
Ok(r) => r, Ok(r) => match r.share_url {
Err(e) => return UploadResult::Err(format!("解析响应失败: {}", e)), Some(url) => UploadResult::Ok(url),
}; None => UploadResult::Err(r.error.unwrap_or_else(|| "未知服务器响应".to_owned())),
},
match result.share_url { Err(e) => UploadResult::Err(format!("解析响应失败: {} - body: {}", e, body)),
Some(url) => UploadResult::Ok(url),
None => UploadResult::Err(result.error.unwrap_or_else(|| "未知服务器响应".to_owned())),
} }
} }
@@ -236,13 +215,14 @@ impl eframe::App for App {
}); });
}); });
ctx.request_repaint_after(std::time::Duration::from_millis(100)); ctx.request_repaint_after(std::time::Duration::from_millis(200));
} }
} }
fn load_chinese_font(ctx: &egui::Context) { fn load_chinese_font(ctx: &egui::Context) {
let font_paths = [ let font_paths = [
"C:\\Windows\\Fonts\\msyh.ttc", "C:\\Windows\\Fonts\\msyh.ttc",
"C:\\Windows\\Fonts\\msyhbd.ttc",
"C:\\Windows\\Fonts\\simhei.ttf", "C:\\Windows\\Fonts\\simhei.ttf",
"C:\\Windows\\Fonts\\simsun.ttc", "C:\\Windows\\Fonts\\simsun.ttc",
]; ];
@@ -250,9 +230,10 @@ fn load_chinese_font(ctx: &egui::Context) {
for path in &font_paths { for path in &font_paths {
if let Ok(data) = std::fs::read(path) { if let Ok(data) = std::fs::read(path) {
let mut fonts = egui::FontDefinitions::default(); let mut fonts = egui::FontDefinitions::default();
fonts fonts.font_data.insert(
.font_data "chinese".to_owned(),
.insert("chinese".to_owned(), std::sync::Arc::new(egui::FontData::from_owned(data))); std::sync::Arc::new(egui::FontData::from_owned(data)),
);
fonts fonts
.families .families
.get_mut(&egui::FontFamily::Proportional) .get_mut(&egui::FontFamily::Proportional)
@@ -262,7 +243,7 @@ fn load_chinese_font(ctx: &egui::Context) {
.families .families
.get_mut(&egui::FontFamily::Monospace) .get_mut(&egui::FontFamily::Monospace)
.unwrap() .unwrap()
.push("chinese".to_owned()); .insert(0, "chinese".to_owned());
ctx.set_fonts(fonts); ctx.set_fonts(fonts);
return; return;
} }