mirror of
https://github.com/lanyeeee/bilibili-video-downloader.git
synced 2026-09-08 17:16:52 +08:00
fix: 修复 HEAD 无法获取 Content-Length 导致选流降级的问题
This commit is contained in:
@@ -746,24 +746,61 @@ impl BiliClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_content_length(&self, media_url: &str) -> anyhow::Result<u64> {
|
pub async fn get_content_length(&self, media_url: &str) -> anyhow::Result<u64> {
|
||||||
let request = self.content_length_client.read().head(media_url);
|
fn parse_content_length(headers: &HeaderMap) -> anyhow::Result<u64> {
|
||||||
let http_resp = request.send().await?;
|
headers
|
||||||
// 检查http响应状态码
|
.get("Content-Length")
|
||||||
let status = http_resp.status();
|
.context("缺少 Content-Length 响应头")?
|
||||||
if status != StatusCode::OK {
|
.to_str()
|
||||||
return Err(anyhow!("预料之外的状态码({status})"));
|
.context("Content-Length 响应头无法转换为字符串")?
|
||||||
|
.parse::<u64>()
|
||||||
|
.context("Content-Length 响应头无法转换为整数")
|
||||||
}
|
}
|
||||||
|
|
||||||
let headers = http_resp.headers();
|
fn parse_total_from_content_range(headers: &HeaderMap) -> anyhow::Result<u64> {
|
||||||
let content_length = headers
|
// Example: "bytes 0-0/12345"
|
||||||
.get("Content-Length")
|
let content_range = headers
|
||||||
.context("缺少 Content-Length 响应头")?
|
.get("Content-Range")
|
||||||
.to_str()
|
.context("缺少 Content-Range 响应头")?
|
||||||
.context("Content-Length 响应头无法转换为字符串")?
|
.to_str()
|
||||||
.parse::<u64>()
|
.context("Content-Range 响应头无法转换为字符串")?;
|
||||||
.context("Content-Length 响应头无法转换为整数")?;
|
|
||||||
|
|
||||||
Ok(content_length)
|
let Some((_, total)) = content_range.split_once('/') else {
|
||||||
|
return Err(anyhow!("预料之外的 Content-Range 格式: {content_range}"));
|
||||||
|
};
|
||||||
|
|
||||||
|
total
|
||||||
|
.parse::<u64>()
|
||||||
|
.context("Content-Range 总大小无法转换为整数")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 优先使用 HEAD 获取 Content-Length
|
||||||
|
let request = self.content_length_client.read().head(media_url);
|
||||||
|
let http_resp = request.send().await?;
|
||||||
|
let status = http_resp.status();
|
||||||
|
if status == StatusCode::OK {
|
||||||
|
if let Ok(content_length) = parse_content_length(http_resp.headers()) {
|
||||||
|
return Ok(content_length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 部分 upos/CDN 对 HEAD 支持不完整(尤其是高码率/高帧率流),这里降级用 Range 请求探测总大小
|
||||||
|
let request = self
|
||||||
|
.content_length_client
|
||||||
|
.read()
|
||||||
|
.get(media_url)
|
||||||
|
.header("range", "bytes=0-0");
|
||||||
|
let http_resp = request.send().await?;
|
||||||
|
let status = http_resp.status();
|
||||||
|
|
||||||
|
if status == StatusCode::PARTIAL_CONTENT {
|
||||||
|
return parse_total_from_content_range(http_resp.headers());
|
||||||
|
}
|
||||||
|
|
||||||
|
if status == StatusCode::OK {
|
||||||
|
return parse_content_length(http_resp.headers());
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(anyhow!("预料之外的状态码({status})"))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_url_with_content_length(&self, urls: Vec<String>) -> Vec<(String, u64)> {
|
pub async fn get_url_with_content_length(&self, urls: Vec<String>) -> Vec<(String, u64)> {
|
||||||
|
|||||||
Reference in New Issue
Block a user