basic download completeness check

This commit is contained in:
polv committed 2026-03-05 16:46:57 +07:00
1 parent ac2ceef948
commit e435ad3a82
4 files changed
+29 -6

No files matched your search

Generated
+1
View File
@@ -518,6 +518,7 @@ dependencies = [
"tauri-plugin-fs", "tauri-plugin-fs",
"tauri-plugin-http", "tauri-plugin-http",
"tauri-plugin-opener", "tauri-plugin-opener",
"zip",
] ]
[[package]] [[package]]
+4 -1
View File
@@ -11,7 +11,10 @@ async function main() {
const { data, error } = await supabase.storage.from("yomitan").list("ja"); const { data, error } = await supabase.storage.from("yomitan").list("ja");
if (error) throw error; if (error) throw error;
if (data) { if (data) {
console.log(data.map((d) => d.id)); console.log(data);
// no sha256, but may be precomputed and manually placed at data[*].metadata.*
// data[*].metadata.{size,contentLength} could be meaningful
// GitHub releases uses digest: 'sha256:*' in assets[*].digest currently
const toDownload = data.filter(() => true); const toDownload = data.filter(() => true);
+1
View File
@@ -26,3 +26,4 @@ anyhow = "1.0.102"
tauri-plugin-fs = "2" tauri-plugin-fs = "2"
serde_json = "1.0.149" serde_json = "1.0.149"
serde = "1.0.228" serde = "1.0.228"
zip = "8.1.0"
+23 -5
View File
@@ -1,9 +1,14 @@
use std::{fs::File, io::Write, path::PathBuf}; use std::{
fs::{File, remove_file},
io::Write,
path::PathBuf,
};
use cjdic2_core::{AppService, CJDicError, SqlParam, YomitanRow, YomitanZipImportResult}; use cjdic2_core::{AppService, CJDicError, SqlParam, YomitanRow, YomitanZipImportResult};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tauri::{AppHandle, Emitter, Manager}; use tauri::{AppHandle, Emitter, Manager};
use tauri_plugin_http::reqwest::Client; use tauri_plugin_http::reqwest::Client;
use zip::ZipArchive;
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct YomitanDictEntry { pub struct YomitanDictEntry {
@@ -27,7 +32,11 @@ pub async fn init_yomitan(
.map_err(|e| CJDicError::Error(e.to_string()))?; .map_err(|e| CJDicError::Error(e.to_string()))?;
for d in dicts.iter().clone() { for d in dicts.iter().clone() {
if !app_dir.join(&d.filepath).exists() { let zip_path = app_dir.join(&d.filepath);
if zip_path.exists() && File::open(zip_path).is_ok_and(|f| ZipArchive::new(f).is_ok()) {
continue;
}
download_url_local( download_url_local(
d.url.clone(), d.url.clone(),
app_dir.clone(), app_dir.clone(),
@@ -39,7 +48,6 @@ pub async fn init_yomitan(
.await .await
.map_err(|e| CJDicError::Error(e.to_string()))?; .map_err(|e| CJDicError::Error(e.to_string()))?;
} }
}
let zip_files: Vec<PathBuf> = dicts let zip_files: Vec<PathBuf> = dicts
.into_iter() .into_iter()
@@ -155,8 +163,6 @@ where
let content_length = response.content_length().unwrap_or(0); let content_length = response.content_length().unwrap_or(0);
let mut file = File::create(&file_pf).map_err(|e| CJDicError::Error(e.to_string()))?; let mut file = File::create(&file_pf).map_err(|e| CJDicError::Error(e.to_string()))?;
println!("{}", content_length);
// Downloading the file in chunks // Downloading the file in chunks
let mut downloaded: u64 = 0; let mut downloaded: u64 = 0;
while let Some(chunk) = response while let Some(chunk) = response
@@ -174,6 +180,18 @@ where
downloaded, downloaded,
}); });
} }
// Verify download completeness
if content_length > 0 && downloaded < content_length {
// Delete incomplete file
drop(file); // ensure file handle is released before deleting
remove_file(&file_pf).ok();
return Err(CJDicError::Error(format!(
"Incomplete download: expected {} bytes, got {}",
content_length, downloaded
)));
}
println!("File downloaded successfully to {:?}", &file_pf); println!("File downloaded successfully to {:?}", &file_pf);
} else { } else {
eprintln!("Failed to download file: {:?}", response.status()); eprintln!("Failed to download file: {:?}", response.status());