From 4734d560215cb7764f0a2f3ebf91e43d6fee0599 Mon Sep 17 00:00:00 2001 From: CJ Pais Date: Thu, 27 Nov 2025 18:23:26 -0800 Subject: [PATCH] fix? (#388) --- src-tauri/src/managers/model.rs | 46 ++++++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/src-tauri/src/managers/model.rs b/src-tauri/src/managers/model.rs index f20b706..f9e4199 100644 --- a/src-tauri/src/managers/model.rs +++ b/src-tauri/src/managers/model.rs @@ -257,7 +257,7 @@ impl ModelManager { } model.is_downloaded = model_path.exists() && model_path.is_dir(); - model.is_downloading = partial_path.exists(); + model.is_downloading = false; // Get partial file size if it exists (for the .tar.gz being downloaded) if partial_path.exists() { @@ -271,7 +271,7 @@ impl ModelManager { let partial_path = self.models_dir.join(format!("{}.partial", &model.filename)); model.is_downloaded = model_path.exists(); - model.is_downloading = partial_path.exists(); + model.is_downloading = false; // Get partial file size if it exists if partial_path.exists() { @@ -339,7 +339,7 @@ impl ModelManager { } // Check if we have a partial download to resume - let resume_from = if partial_path.exists() { + let mut resume_from = if partial_path.exists() { let size = partial_path.metadata()?.len(); info!("Resuming download of model {} from byte {}", model_id, size); size @@ -364,7 +364,25 @@ impl ModelManager { request = request.header("Range", format!("bytes={}-", resume_from)); } - let response = request.send().await?; + let mut response = request.send().await?; + + // If we tried to resume but server returned 200 (not 206 Partial Content), + // the server doesn't support range requests. Delete partial file and restart + // fresh to avoid file corruption (appending full file to partial). + if resume_from > 0 && response.status() == reqwest::StatusCode::OK { + warn!( + "Server doesn't support range requests for model {}, restarting download", + model_id + ); + drop(response); + let _ = fs::remove_file(&partial_path); + + // Reset resume_from since we're starting fresh + resume_from = 0; + + // Restart download without range header + response = client.get(&url).send().await?; + } // Check for success or partial content status if !response.status().is_success() @@ -454,6 +472,26 @@ impl ModelManager { file.flush()?; drop(file); // Ensure file is closed before moving + // Verify downloaded file size matches expected size + if total_size > 0 { + let actual_size = partial_path.metadata()?.len(); + if actual_size != total_size { + // Download is incomplete/corrupted - delete partial and return error + let _ = fs::remove_file(&partial_path); + { + let mut models = self.available_models.lock().unwrap(); + if let Some(model) = models.get_mut(model_id) { + model.is_downloading = false; + } + } + return Err(anyhow::anyhow!( + "Download incomplete: expected {} bytes, got {} bytes", + total_size, + actual_size + )); + } + } + // Handle directory-based models (extract tar.gz) vs file-based models if model_info.is_directory { // Emit extraction started event