~修复和优化curl进度条显示功能

This commit is contained in:
juewuy
2026-02-08 21:26:53 +08:00
parent b6bc1e9f72
commit e5489f3c91
2 changed files with 58 additions and 67 deletions

View File

@@ -10,60 +10,6 @@ webget(){
url=$(printf '%s\n' "$2" | url=$(printf '%s\n' "$2" |
sed 's#https://raw.githubusercontent.com/juewuy/ShellCrash/#https://testingcf.jsdelivr.net/gh/juewuy/ShellCrash@#') sed 's#https://raw.githubusercontent.com/juewuy/ShellCrash/#https://testingcf.jsdelivr.net/gh/juewuy/ShellCrash@#')
fi fi
# === 新增模块 1大小探测 (仅显示用) ===
fsize_raw=0
if [ "$3" != "echooff" ]; then
# 探测头信息
header=$(curl -sIL --connect-timeout 2 "$url")
# 代理容错
[ -z "$header" ] && { export https_proxy=""; export http_proxy=""; header=$(curl -sIL --connect-timeout 2 "$url"); }
# 提取大小 (优先 Content-Length其次 ETag)
fsize_raw=$(echo "$header" | grep -i 'Content-Length' | tail -n 1 | awk '{print $2}' | tr -d '\r' | awk '{print int($1)}')
if [ -z "$fsize_raw" ] || [ "$fsize_raw" -eq 0 ]; then
etag=$(echo "$header" | grep -i 'etag' | tail -n 1 | cut -d '"' -f2 | cut -d '-' -f1)
[ -n "$etag" ] && fsize_raw=$(printf "%d" 0x$etag 2>/dev/null)
fi
# 显示文件大小
[ -n "$fsize_raw" ] && [ "$fsize_raw" -gt 0 ] && echo "文件大小: $(awk -v n=$fsize_raw 'BEGIN {printf "%.2f", n/1048576}') MB"
fi
# === 新增模块 2手搓进度条引擎 (函数定义) ===
execute_curl(){
local path="$1" target_url="$2" total_size="$3" extra_args="$4"
rm -f /tmp/webget_res
# 后台静默下载,状态码写入临时文件
curl $extra_args -s -L -w '%{http_code}' "$target_url" -o "$path" > /tmp/webget_res &
local pid=$!
# 循环监控
while kill -0 $pid 2>/dev/null; do
if [ -f "$path" ]; then
local curr=$(wc -c < "$path")
local pct=$(awk -v c=$curr -v t=$total_size 'BEGIN {p=(c*100/t); if(p>100)p=100; printf "%.1f", p}')
# 40字符安全宽度
local bar_max=40
local num=$(awk -v p=$pct -v w=$bar_max 'BEGIN {printf "%d", p*w/100}')
local bar=$(printf "%${num}s" | tr ' ' '#'); local spc_n=$((bar_max - num))
local spc=""; [ "$spc_n" -gt 0 ] && spc=$(printf "%${spc_n}s")
# \033[2K 清除整行
printf "\r\033[2K%s%s %6s%%" "$bar" "$spc" "$pct" >&2
fi
usleep 200000 2>/dev/null || sleep 1
done
local code=$(cat /tmp/webget_res 2>/dev/null)
if [ "$code" = "200" ] || [ "$code" = "206" ]; then
local full=$(printf "%40s" | tr ' ' '#')
printf "\r\033[2K%s 100.0%%\n" "$full" >&2
else
printf "\r\033[2K" >&2; [ -f "$path" ] && rm -f "$path"
fi
echo "$code"
}
# =============================================== # ===============================================
#参数【$1】代表下载目录【$2】代表在线地址 #参数【$1】代表下载目录【$2】代表在线地址
@@ -82,39 +28,37 @@ webget(){
wget -Y off $agent $progress $redirect $certificate --timeout=5 -O "$1" "$2" wget -Y off $agent $progress $redirect $certificate --timeout=5 -O "$1" "$2"
return $? return $?
elif curl --version >/dev/null 2>&1; then elif curl --version >/dev/null 2>&1; then
[ "$3" = "echooff" ] && progress='-s' || progress='-#' if [ "$3" = "echooff" ];then
progress='-s'
elif echo "$url" | grep -q 'jsdelivr.net';then
progress='-#'
. "$CRASHDIR"/libs/web_get_curlbar.sh && curl_fsize
else
progress='-#'
fi
[ "$4" = "rediroff" ] && redirect='' || redirect='-L' [ "$4" = "rediroff" ] && redirect='' || redirect='-L'
if [ "$5" = "skipceroff" ] || [ "$skip_cert" = OFF ];then if [ "$5" = "skipceroff" ] || [ "$skip_cert" = OFF ];then
certificate='' certificate=''
else else
certificate='-k' certificate='-k'
fi fi
# curl 特殊版本兼容
# 判断是否启用手搓进度条 (CDN 且 非静默 且 有大小)
use_manual_bar="" # <--- 这里加上了初始化
has_cl=$(echo "$header" | grep -iq 'Content-Length' && echo "yes")
[ "$3" != "echooff" ] && [ "$has_cl" != "yes" ] && [ "$fsize_raw" -gt 0 ] && use_manual_bar="yes"
auth_arg="" auth_arg=""
if curl --version | grep -q '^curl 8.' && ckcmd base64; then if curl --version | grep -q '^curl 8.' && ckcmd base64; then
auth_b64=$(printf '%s' "$authentication" | base64) auth_b64=$(printf '%s' "$authentication" | base64)
[ -n "$auth_b64" ] && auth_arg="--proxy-header Proxy-Authorization:Basic $auth_b64" [ -n "$auth_b64" ] && auth_arg="--proxy-header Proxy-Authorization:Basic $auth_b64"
fi fi
if [ -n "$fsize_raw" ] && [ "$fsize_raw" -gt 204800 ]; then
# --- 第一次下载 ---
if [ "$use_manual_bar" = "yes" ]; then
result=$(execute_curl "$1" "$url" "$fsize_raw" "$agent $auth_arg $redirect $certificate") result=$(execute_curl "$1" "$url" "$fsize_raw" "$agent $auth_arg $redirect $certificate")
else else
result=$(curl $agent $auth_arg -w '%{http_code}' --connect-timeout 3 $progress $redirect $certificate -o "$1" "$url") result=$(curl $agent $auth_arg -w '%{http_code}' --connect-timeout 3 $progress $redirect $certificate -o "$1" "$url")
fi fi
[ "$result" = "200" ] && return 0 #成功则退出否则重试 [ "$result" = "200" ] && return 0 #成功则退出否则重试
# --- Fallback 重试 ---
export https_proxy="" export https_proxy=""
export http_proxy="" export http_proxy=""
if [ "$use_manual_bar" = "yes" ]; then if [ -n "$fsize_raw" ] && [ "$fsize_raw" -gt 204800 ]; then
result=$(execute_curl "$1" "$2" "$fsize_raw" "$agent $redirect $certificate") result=$(execute_curl "$1" "$2" "$fsize_raw" "$agent $redirect $certificate")
else else
result=$(curl $agent -w '%{http_code}' --connect-timeout 5 $progress $redirect $certificate -o "$1" "$2") result=$(curl $agent -w '%{http_code}' --connect-timeout 5 $progress $redirect $certificate -o "$1" "$2")

View File

@@ -0,0 +1,47 @@
bar_max=42 #进度条长度
curl_fsize(){ # 获取文件大小
fsize_raw=0
header=$(curl -sIL --connect-timeout 2 "$url")
# 代理容错
[ -z "$header" ] && { export https_proxy=""; export http_proxy=""; header=$(curl -sIL --connect-timeout 2 "$url"); }
# 提取大小 (优先 Content-Length其次 ETag)
fsize_raw=$(echo "$header" | grep -i 'Content-Length' | tail -n 1 | awk '{print $2}' | tr -d '\r' | awk '{print int($1)}')
if [ -z "$fsize_raw" ] || [ "$fsize_raw" -eq 0 ]; then
etag=$(echo "$header" | grep -i 'etag' | tail -n 1 | cut -d '"' -f2 | cut -d '-' -f1)
[ -n "$etag" ] && fsize_raw=$(printf "%d" 0x$etag 2>/dev/null)
fi
}
execute_curl(){ # 手搓curl进度条
local path="$1" target_url="$2" total_size="$3" extra_args="$4"
rm -f /tmp/webget_res
# 后台静默下载,状态码写入临时文件
curl $extra_args -s -L -w '%{http_code}' "$target_url" -o "$path" > /tmp/webget_res &
local pid=$!
# 循环监控
while kill -0 $pid 2>/dev/null; do
if [ -f "$path" ]; then
local curr=$(wc -c < "$path")
local pct=$(awk -v c=$curr -v t=$total_size 'BEGIN {p=(c*100/t); if(p>100)p=100; printf "%.1f", p}')
local num=$(awk -v p=$pct -v w=$bar_max 'BEGIN {printf "%d", p*w/100}')
local bar=$(printf "%${num}s" | tr ' ' '#'); local spc_n=$((bar_max - num))
local spc=""; [ "$spc_n" -gt 0 ] && spc=$(printf "%${spc_n}s")
local size=$(( fsize_raw * 100 / 1048576 ))
local fs="$((size / 100)).$((size % 100)) MB"
printf "\r\033[2K%s%s %6s%%(%s)" "$bar" "$spc" "$pct" "$fs" >&2
fi
usleep 200000 2>/dev/null || sleep 1
done
local code=$(cat /tmp/webget_res 2>/dev/null)
if [ "$code" = "200" ] || [ "$code" = "206" ]; then
local full=$(printf "%${bar_max}s" | tr ' ' '#')
printf "\r\033[2K%s 100.0%%(%s)\n" "$full" "$fs" >&2
else
printf "\r\033[2K" >&2; [ -f "$path" ] && rm -f "$path"
fi
echo "$code"
}