[feat] optimize tauri write binary file
This commit is contained in:
@@ -23,6 +23,10 @@ zip = "0.6.6"
|
|||||||
tar = "0.4.40"
|
tar = "0.4.40"
|
||||||
eventsource-client = "0.12.2"
|
eventsource-client = "0.12.2"
|
||||||
futures = "0.3.30"
|
futures = "0.3.30"
|
||||||
|
actix-web = "4.0"
|
||||||
|
actix-cors = "0.6"
|
||||||
|
actix-rt = "2.5"
|
||||||
|
url = "2.2"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
# this feature is used for production builds or when `devPath` points to the filesystem
|
# this feature is used for production builds or when `devPath` points to the filesystem
|
||||||
|
|||||||
@@ -15,6 +15,10 @@ use std::io::Write;
|
|||||||
use std::{time::Duration, path::Path};
|
use std::{time::Duration, path::Path};
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use actix_cors::Cors;
|
||||||
|
use tauri::api::path::app_data_dir;
|
||||||
|
use actix_web::{web, HttpRequest, HttpResponse, HttpServer, Responder, App, post, get};
|
||||||
|
use std::fs::File;
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
async fn native_request(url: String, body: String, header: String, method:String) -> String {
|
async fn native_request(url: String, body: String, header: String, method:String) -> String {
|
||||||
@@ -448,6 +452,33 @@ async fn streamed_fetch(id:String, url:String, headers: String, body: String, ha
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[post("/")]
|
||||||
|
async fn write_binary_file_to_appdata(req: HttpRequest, body: web::Bytes, app_handle: web::Data<tauri::AppHandle>) -> impl Responder {
|
||||||
|
let query = req.query_string();
|
||||||
|
let params: std::collections::HashMap<_, _> = url::form_urlencoded::parse(query.as_bytes()).into_owned().collect();
|
||||||
|
let app_data_dir = app_data_dir(&app_handle.config()).expect("App dir must be returned by tauri");
|
||||||
|
if let Some(file_path) = params.get("path") {
|
||||||
|
let full_path = app_data_dir.join(file_path);
|
||||||
|
if let Some(parent) = Path::new(&full_path).parent() {
|
||||||
|
if let Err(e) = std::fs::create_dir_all(parent) {
|
||||||
|
return HttpResponse::InternalServerError().body(format!("Failed to create directories: {}", e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match File::create(&full_path) {
|
||||||
|
Ok(mut file) => {
|
||||||
|
if let Err(e) = file.write_all(&body) {
|
||||||
|
return HttpResponse::InternalServerError().body(format!("Failed to write to file: {}", e));
|
||||||
|
}
|
||||||
|
HttpResponse::Ok().body("File written successfully")
|
||||||
|
}
|
||||||
|
Err(e) => HttpResponse::InternalServerError().body(format!("Failed to create file: {}", e)),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
HttpResponse::BadRequest().body("Missing file path in query string")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
tauri::Builder::default()
|
tauri::Builder::default()
|
||||||
.invoke_handler(tauri::generate_handler![
|
.invoke_handler(tauri::generate_handler![
|
||||||
@@ -463,6 +494,29 @@ fn main() {
|
|||||||
install_py_dependencies,
|
install_py_dependencies,
|
||||||
streamed_fetch
|
streamed_fetch
|
||||||
])
|
])
|
||||||
|
.setup(|app| {
|
||||||
|
let handle = app.handle().clone();
|
||||||
|
tauri::async_runtime::spawn(async move {
|
||||||
|
HttpServer::new(move || {
|
||||||
|
App::new()
|
||||||
|
.wrap(
|
||||||
|
Cors::default()
|
||||||
|
.allow_any_origin()
|
||||||
|
.allow_any_method()
|
||||||
|
.allow_any_header()
|
||||||
|
.max_age(3600)
|
||||||
|
)
|
||||||
|
.app_data(web::PayloadConfig::new(1024 * 1024 * 1024)) // 1 GB
|
||||||
|
.app_data(web::Data::new(handle.clone()))
|
||||||
|
.service(write_binary_file_to_appdata)
|
||||||
|
})
|
||||||
|
.bind(("127.0.0.1", 5354))
|
||||||
|
.expect("Failed to bind to port 5354")
|
||||||
|
.run()
|
||||||
|
.await;
|
||||||
|
});
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
.run(tauri::generate_context!())
|
.run(tauri::generate_context!())
|
||||||
.expect("error while running tauri application");
|
.expect("error while running tauri application");
|
||||||
}
|
}
|
||||||
@@ -474,4 +528,4 @@ fn header_map_to_json(header_map: &HeaderMap) -> serde_json::Value {
|
|||||||
map.insert(key.as_str().to_string(), value.to_str().unwrap().to_string());
|
map.insert(key.as_str().to_string(), value.to_str().unwrap().to_string());
|
||||||
}
|
}
|
||||||
json!(map)
|
json!(map)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,6 +55,22 @@ interface fetchLog{
|
|||||||
|
|
||||||
let fetchLog:fetchLog[] = []
|
let fetchLog:fetchLog[] = []
|
||||||
|
|
||||||
|
async function writeBinaryFileFast(appPath: string, data: Uint8Array) {
|
||||||
|
const apiUrl = `http://127.0.0.1:5354/?path=${encodeURIComponent(appPath)}`;
|
||||||
|
|
||||||
|
const response = await fetch(apiUrl, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/octet-stream'
|
||||||
|
},
|
||||||
|
body: new Blob([data])
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`HTTP error! status: ${response.status}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export async function downloadFile(name:string, dat:Uint8Array|ArrayBuffer|string) {
|
export async function downloadFile(name:string, dat:Uint8Array|ArrayBuffer|string) {
|
||||||
if(typeof(dat) === 'string'){
|
if(typeof(dat) === 'string'){
|
||||||
dat = Buffer.from(dat, 'utf-8')
|
dat = Buffer.from(dat, 'utf-8')
|
||||||
@@ -233,7 +249,7 @@ export async function saveAsset(data:Uint8Array, customId:string = '', fileName:
|
|||||||
fileExtension = fileName.split('.').pop()
|
fileExtension = fileName.split('.').pop()
|
||||||
}
|
}
|
||||||
if(isTauri){
|
if(isTauri){
|
||||||
await writeBinaryFile(`assets/${id}.${fileExtension}`, data ,{dir: BaseDirectory.AppData})
|
await writeBinaryFileFast(`assets/${id}.${fileExtension}`, data);
|
||||||
return `assets/${id}.${fileExtension}`
|
return `assets/${id}.${fileExtension}`
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
@@ -299,8 +315,8 @@ export async function saveDb(){
|
|||||||
db.saveTime = Math.floor(Date.now() / 1000)
|
db.saveTime = Math.floor(Date.now() / 1000)
|
||||||
const dbData = encodeRisuSave(db)
|
const dbData = encodeRisuSave(db)
|
||||||
if(isTauri){
|
if(isTauri){
|
||||||
await writeBinaryFile('database/database.bin', dbData, {dir: BaseDirectory.AppData})
|
await writeBinaryFileFast('database/database.bin', dbData);
|
||||||
await writeBinaryFile(`database/dbbackup-${(Date.now()/100).toFixed()}.bin`, dbData, {dir: BaseDirectory.AppData})
|
await writeBinaryFileFast(`database/dbbackup-${(Date.now()/100).toFixed()}.bin`, dbData);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
if(!forageStorage.isAccount){
|
if(!forageStorage.isAccount){
|
||||||
@@ -393,9 +409,7 @@ export async function loadData() {
|
|||||||
await createDir('assets', {dir: BaseDirectory.AppData})
|
await createDir('assets', {dir: BaseDirectory.AppData})
|
||||||
}
|
}
|
||||||
if(!await exists('database/database.bin', {dir: BaseDirectory.AppData})){
|
if(!await exists('database/database.bin', {dir: BaseDirectory.AppData})){
|
||||||
await writeBinaryFile('database/database.bin',
|
await writeBinaryFileFast('database/database.bin', encodeRisuSave({}));
|
||||||
encodeRisuSave({})
|
|
||||||
,{dir: BaseDirectory.AppData})
|
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
setDatabase(
|
setDatabase(
|
||||||
@@ -1586,4 +1600,4 @@ export class BlankWriter{
|
|||||||
async end(){
|
async end(){
|
||||||
//do nothing, just to make compatible with other writer
|
//do nothing, just to make compatible with other writer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user