fix(desktop): rewrite upload with blocking reqwest, remove tokio dependency
This commit is contained in:
@@ -5,8 +5,7 @@ edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
eframe = "0.31"
|
||||
reqwest = { version = "0.12", default-features = false, features = ["rustls-tls", "multipart"] }
|
||||
tokio = { version = "1", features = ["rt", "macros"] }
|
||||
reqwest = { version = "0.12", default-features = false, features = ["rustls-tls", "multipart", "blocking"] }
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
|
||||
|
||||
@@ -1,15 +1,11 @@
|
||||
#![windows_subsystem = "windows"]
|
||||
|
||||
use eframe::egui;
|
||||
use reqwest::multipart;
|
||||
use reqwest::blocking::multipart;
|
||||
use std::sync::mpsc;
|
||||
|
||||
#[derive(serde::Deserialize)]
|
||||
struct UploadResponse {
|
||||
#[allow(dead_code)]
|
||||
id: Option<String>,
|
||||
#[allow(dead_code)]
|
||||
filename: Option<String>,
|
||||
share_url: Option<String>,
|
||||
error: Option<String>,
|
||||
}
|
||||
@@ -43,27 +39,9 @@ impl App {
|
||||
self.upload_rx = Some(rx);
|
||||
self.uploading = true;
|
||||
|
||||
let filename = filepath
|
||||
.file_name()
|
||||
.unwrap_or_default()
|
||||
.to_string_lossy()
|
||||
.to_string();
|
||||
|
||||
std::thread::spawn(move || {
|
||||
let rt = tokio::runtime::Builder::new_current_thread()
|
||||
.enable_all()
|
||||
.build();
|
||||
match rt {
|
||||
Ok(rt) => {
|
||||
let result = rt.block_on(async {
|
||||
do_upload(&api_url, &filepath, &filename).await
|
||||
});
|
||||
let result = do_upload(&api_url, &filepath);
|
||||
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) {
|
||||
Ok(d) => d,
|
||||
Err(e) => return UploadResult::Err(format!("读取文件失败: {}", e)),
|
||||
};
|
||||
|
||||
let part = multipart::Part::bytes(data)
|
||||
.file_name(filename.to_owned())
|
||||
.mime_str("application/octet-stream")
|
||||
.unwrap_or_else(|_| multipart::Part::bytes(vec![]).file_name(filename.to_owned()));
|
||||
|
||||
let part = multipart::Part::bytes(data).file_name(filename);
|
||||
let form = multipart::Form::new()
|
||||
.part("file", part)
|
||||
.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,
|
||||
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,
|
||||
Err(e) => return UploadResult::Err(format!("请求失败: {}", e)),
|
||||
Err(e) => return UploadResult::Err(format!("网络请求失败: {}", e)),
|
||||
};
|
||||
|
||||
let status = resp.status();
|
||||
let body = match resp.text().await {
|
||||
let body = match resp.text() {
|
||||
Ok(b) => b,
|
||||
Err(e) => return UploadResult::Err(format!("读取响应失败: {}", e)),
|
||||
};
|
||||
|
||||
if !status.is_success() {
|
||||
let err: UploadResponse = serde_json::from_str(&body).unwrap_or(UploadResponse {
|
||||
id: None,
|
||||
filename: None,
|
||||
share_url: None,
|
||||
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) {
|
||||
Ok(r) => r,
|
||||
Err(e) => return UploadResult::Err(format!("解析响应失败: {}", e)),
|
||||
};
|
||||
|
||||
match result.share_url {
|
||||
match serde_json::from_str::<UploadResponse>(&body) {
|
||||
Ok(r) => match r.share_url {
|
||||
Some(url) => UploadResult::Ok(url),
|
||||
None => UploadResult::Err(result.error.unwrap_or_else(|| "未知服务器响应".to_owned())),
|
||||
None => UploadResult::Err(r.error.unwrap_or_else(|| "未知服务器响应".to_owned())),
|
||||
},
|
||||
Err(e) => UploadResult::Err(format!("解析响应失败: {} - body: {}", e, body)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
let font_paths = [
|
||||
"C:\\Windows\\Fonts\\msyh.ttc",
|
||||
"C:\\Windows\\Fonts\\msyhbd.ttc",
|
||||
"C:\\Windows\\Fonts\\simhei.ttf",
|
||||
"C:\\Windows\\Fonts\\simsun.ttc",
|
||||
];
|
||||
@@ -250,9 +230,10 @@ fn load_chinese_font(ctx: &egui::Context) {
|
||||
for path in &font_paths {
|
||||
if let Ok(data) = std::fs::read(path) {
|
||||
let mut fonts = egui::FontDefinitions::default();
|
||||
fonts
|
||||
.font_data
|
||||
.insert("chinese".to_owned(), std::sync::Arc::new(egui::FontData::from_owned(data)));
|
||||
fonts.font_data.insert(
|
||||
"chinese".to_owned(),
|
||||
std::sync::Arc::new(egui::FontData::from_owned(data)),
|
||||
);
|
||||
fonts
|
||||
.families
|
||||
.get_mut(&egui::FontFamily::Proportional)
|
||||
@@ -262,7 +243,7 @@ fn load_chinese_font(ctx: &egui::Context) {
|
||||
.families
|
||||
.get_mut(&egui::FontFamily::Monospace)
|
||||
.unwrap()
|
||||
.push("chinese".to_owned());
|
||||
.insert(0, "chinese".to_owned());
|
||||
ctx.set_fonts(fonts);
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user