优化调整、BT下载(有bug)

This commit is contained in:
zhongluofeng
2026-08-27 18:25:45 +08:00
parent 4dd60f42a1
commit d21649c60e
34 changed files with 4991 additions and 198 deletions
+53 -4
View File
@@ -53,14 +53,34 @@ impl HttpDownloader {
}
/// 探测下载资源信息(大小、是否支持 Range、文件名)
/// 优先用 GET + Range: bytes=0-0(返回 206 + Content-Range),回退到 HEAD
/// 优先用 GET + Range: bytes=0-0(返回 206 + Content-Range),回退到 HEAD
/// 代理降级:use_proxy=true 时先走系统代理,失败则回退 no_proxy 直连重试一次
pub async fn probe(
&self,
url: &str,
headers: &HashMap<String, String>,
use_proxy: bool,
) -> Result<ProbeResult, String> {
let client = self.client(use_proxy);
let first = self.client(use_proxy);
match self.probe_with_client(first, url, headers).await {
Ok(r) => return Ok(r),
Err(e) if use_proxy => {
let direct = self.client(false);
self.probe_with_client(direct, url, headers)
.await
.map_err(|e2| format!("代理探测失败({}),直连重试也失败({}", e, e2))
}
Err(e) => Err(e),
}
}
/// 用指定 client 执行探测(GET Range → 回退 HEAD),供代理降级复用
async fn probe_with_client(
&self,
client: &Client,
url: &str,
headers: &HashMap<String, String>,
) -> Result<ProbeResult, String> {
// 先尝试 Range 请求(能同时判断 Accept-Ranges 和获取大小)
let mut req = client
.get(url)
@@ -165,7 +185,36 @@ impl HttpDownloader {
limiter: Arc<RateLimiter>,
use_proxy: bool,
) -> Result<(), String> {
let client = self.client(use_proxy);
// 代理降级:仅当 use_proxy=true 才有"走代理→失败回退直连"的意义。
// use_proxy=false 直接用直连客户端,无需回退。
// 注意:用户主动暂停/取消(返回"已取消")必须原样透传,不能触发代理回退,
// 否则会把"已取消"包装成"代理失败",导致引擎将其误判为错误而非暂停。
let first = self.client(use_proxy);
match self.download_with_client(first, url, headers, segments, file_path, cancel.clone(), progress, &limiter).await {
Ok(()) => return Ok(()),
Err(e) if use_proxy && e != "已取消" => {
// 回退直连重试(不继承 use_proxy,保证用 no_proxy 客户端)
let direct = self.client(false);
self.download_with_client(direct, url, headers, segments, file_path, cancel, progress, &limiter)
.await
.map_err(|e2| format!("代理下载失败({}),直连重试也失败({}", e, e2))
}
Err(e) => Err(e),
}
}
/// 用指定 client 执行下载(支持单线程与多线程分段),供代理降级复用
async fn download_with_client(
&self,
client: &Client,
url: &str,
headers: &HashMap<String, String>,
segments: &[Segment],
file_path: &Path,
cancel: Arc<AtomicBool>,
progress: &[Arc<AtomicU64>],
limiter: &Arc<RateLimiter>,
) -> Result<(), String> {
let total_size = segments.iter().map(|s| s.len()).sum();
// 预分配文件(若已知大小)
@@ -191,7 +240,7 @@ impl HttpDownloader {
// 单线程下载(不支持 Range 或文件太小)
let seg = &segments[0];
let prog = &progress[0];
self.download_segment(url, headers, seg, file_path, cancel.clone(), prog.clone(), limiter, client)
self.download_segment(url, headers, seg, file_path, cancel.clone(), prog.clone(), limiter.clone(), client)
.await?;
return Ok(());
}