mirror of
https://github.com/yuhkix/wuwa-downloader.git
synced 2025-06-06 01:43:40 +00:00
Add support for resuming partial downloads using HTTP Range requests
- Modified `download_single_file` to check for an existing partially downloaded file - If present, uses HTTP Range headers to resume the download from the last byte - Opens file in append mode rather than overwriting it - Handles HTTP 206 Partial Content and 416 Range Not Satisfiable responses - Updates progress bar and download state accordingly during resumed downloads
This commit is contained in:
parent
cc837ec0cf
commit
bece26c433
1 changed files with 35 additions and 9 deletions
|
@ -6,7 +6,7 @@ use serde_json::{Value, from_reader, from_str};
|
||||||
#[cfg(not(target_os = "windows"))]
|
#[cfg(not(target_os = "windows"))]
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
use std::{
|
use std::{
|
||||||
fs,
|
fs::{self, OpenOptions},
|
||||||
io::{self, Read, Write},
|
io::{self, Read, Write},
|
||||||
path::Path,
|
path::Path,
|
||||||
time::Duration,
|
time::Duration,
|
||||||
|
@ -322,6 +322,7 @@ pub fn download_file(
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn download_single_file(
|
fn download_single_file(
|
||||||
client: &Client,
|
client: &Client,
|
||||||
url: &str,
|
url: &str,
|
||||||
|
@ -330,20 +331,45 @@ fn download_single_file(
|
||||||
progress: &DownloadProgress,
|
progress: &DownloadProgress,
|
||||||
pb: &ProgressBar,
|
pb: &ProgressBar,
|
||||||
) -> Result<(), String> {
|
) -> Result<(), String> {
|
||||||
let mut response = client
|
let mut downloaded: u64 = 0;
|
||||||
|
if path.exists() {
|
||||||
|
downloaded = fs::metadata(path)
|
||||||
|
.map_err(|e| format!("Metadata error: {}", e))?
|
||||||
|
.len();
|
||||||
|
}
|
||||||
|
|
||||||
|
let request = client
|
||||||
.get(url)
|
.get(url)
|
||||||
.timeout(DOWNLOAD_TIMEOUT)
|
.timeout(DOWNLOAD_TIMEOUT);
|
||||||
|
|
||||||
|
let request = if downloaded > 0 {
|
||||||
|
request.header("Range", format!("bytes={}-", downloaded))
|
||||||
|
} else {
|
||||||
|
request
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut response = request
|
||||||
.send()
|
.send()
|
||||||
.map_err(|e| format!("Network error: {}", e))?;
|
.map_err(|e| format!("Network error: {}", e))?;
|
||||||
|
|
||||||
if !response.status().is_success() {
|
if response.status() == reqwest::StatusCode::RANGE_NOT_SATISFIABLE {
|
||||||
return Err(format!("HTTP error: {}", response.status()));
|
return Err("Range not satisfiable. File may already be fully downloaded.".into());
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut file = fs::File::create(path).map_err(|e| format!("File error: {}", e))?;
|
if !response.status().is_success() && response.status() != reqwest::StatusCode::PARTIAL_CONTENT {
|
||||||
|
return Err(format!("HTTP error: {}", response.status()));
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut file = OpenOptions::new()
|
||||||
|
.create(true)
|
||||||
|
.append(true)
|
||||||
|
.open(path)
|
||||||
|
.map_err(|e| format!("File error: {}", e))?;
|
||||||
|
|
||||||
|
pb.set_position(downloaded);
|
||||||
|
progress.downloaded_bytes.store(downloaded, std::sync::atomic::Ordering::SeqCst);
|
||||||
|
|
||||||
let mut buffer = [0; BUFFER_SIZE];
|
let mut buffer = [0; BUFFER_SIZE];
|
||||||
let mut downloaded: u64 = 0;
|
|
||||||
loop {
|
loop {
|
||||||
if should_stop.load(std::sync::atomic::Ordering::SeqCst) {
|
if should_stop.load(std::sync::atomic::Ordering::SeqCst) {
|
||||||
return Err("Download interrupted".into());
|
return Err("Download interrupted".into());
|
||||||
|
@ -364,7 +390,7 @@ fn download_single_file(
|
||||||
pb.set_position(downloaded);
|
pb.set_position(downloaded);
|
||||||
progress
|
progress
|
||||||
.downloaded_bytes
|
.downloaded_bytes
|
||||||
.fetch_add(bytes_read as u64, std::sync::atomic::Ordering::SeqCst);
|
.store(downloaded, std::sync::atomic::Ordering::SeqCst);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -541,7 +567,7 @@ pub fn fetch_gist(client: &Client) -> Result<String, String> {
|
||||||
("live", "os", "Live - OS"),
|
("live", "os", "Live - OS"),
|
||||||
("live", "cn", "Live - CN"),
|
("live", "cn", "Live - CN"),
|
||||||
("beta", "os", "Beta - OS"),
|
("beta", "os", "Beta - OS"),
|
||||||
("beta", "cn", "Beta - CN (wicked-waifus-rs)"),
|
("beta", "cn", "Beta - CN"),
|
||||||
];
|
];
|
||||||
|
|
||||||
println!("{} Available versions:", Status::info());
|
println!("{} Available versions:", Status::info());
|
||||||
|
|
Loading…
Reference in a new issue