工具
下载工具:aria2 与自制的 pget
单线程下载大文件时,你可能只用到了一半带宽。
2026-11 · 约 6 分钟
为什么需要多线程下载
单条连接的速度受两个因素限制:窗口大小和往返延迟。 延迟越高(比如跨国、跨运营商),单连接能跑满的带宽就越低。
开多个连接就能绕开这个限制——每个连接各拉一段,合起来吃满带宽。
实测一个 200MB 文件:
| 方式 | 速度 |
|---|---|
| 单线程 curl | 24.9 MB/s |
| aria2 -x16 -s16 | 36.6 MB/s |
| pget 8 线程 | 40.0 MB/s |
但分片只在「服务器单连接被限速」时才有意义。 有些站单流本来就不限速(比如 GitHub),分片反而更慢—— 实测 39MB 文件:单流 15 MB/s,8 线程只有 9.8 MB/s。
一、aria2:功能最全
macOS 不自带,Homebrew 一条命令:
brew install aria2
常用命令
# 普通下载(16 连接)
aria2c -x16 -s16 -k1M https://example.com/file.iso
# 断点续传(断了重跑同一条命令即可)
aria2c -c -x16 -s16 https://example.com/file.iso
# 指定目录和文件名
aria2c -x16 -s16 -d ~/Downloads -o ubuntu.iso https://example.com/ubuntu.iso
# 限速,别把带宽占满
aria2c -x8 --max-download-limit=20M https://example.com/file.iso
参数说明:
| 参数 | 含义 |
|---|---|
-x | 单服务器最多连接数 |
-s | 文件切成几段 |
-k | 每段最小大小(太小反而增加开销) |
-c | 断点续传 |
小文件把 -x / -s 降到 4~8 更合适,
16 连接对 10MB 的文件纯属浪费。
二、pget:不装任何东西的多线程下载
不想装 aria2 的话,macOS 自带的 curl 就够了。原理是用 HTTP 的
Range 头把文件切成几段,并发下载后拼接。
#!/bin/sh
# pget —— 多线程分片下载(纯 curl 实现)
# 用法: pget <URL> [线程数] [输出文件]
URL="${1:-}"; N="${2:-8}"; OUT="${3:-}"
[ -z "$URL" ] && { echo "用法: pget [线程数] [输出]"; exit 1; }
[ -z "$OUT" ] && OUT=$(basename "${URL%%\?*}")
# 取文件大小
SIZE=$(curl -sIL --max-time 20 "$URL" 2>/dev/null \
| awk 'tolower($1)=="content-length:" {v=$2} END {print v}' | tr -d '\r')
[ -z "$SIZE" ] && exec curl -L -o "$OUT" "$URL"
# 检查是否支持 Range(取最后一个状态行,跳过重定向)
STATUS=$(curl -sIL --max-time 20 -H "Range: bytes=0-1" "$URL" 2>/dev/null \
| awk '/^HTTP/ {s=$2} END {print s}')
[ "$STATUS" != "206" ] && exec curl -L -o "$OUT" "$URL"
TMP=$(mktemp -d); CHUNK=$(( (SIZE + N - 1) / N ))
echo "大小 $((SIZE/1048576)) MB,$N 段并发"
i=0
while [ "$i" -lt "$N" ]; do
S=$((i*CHUNK)); E=$((S+CHUNK-1)); [ "$E" -ge "$SIZE" ] && E=$((SIZE-1))
curl -sL --max-time 3600 -r "${S}-${E}" \
-o "$TMP/part.$(printf '%03d' "$i")" "$URL" &
i=$((i+1))
done
wait
: > "$OUT"; i=0
while [ "$i" -lt "$N" ]; do
cat "$TMP/part.$(printf '%03d' "$i")" >> "$OUT"; i=$((i+1))
done
rm -rf "$TMP"
echo "完成: $OUT ($(wc -c < "$OUT") 字节)"
几个实现细节
- Range 检测要取最后一个状态行。带重定向的 URL 会有多个
HTTP/xxx响应头,只看第一行会拿到 302 而不是 206,误判为「不支持分片」 - 分段文件名要补零(
part.000而不是part.0), 否则按字典序拼接会变成 0、1、10、11、2…,文件直接损坏 - 拼接要按顺序循环,别用
cat part.*
第一个坑我踩过:最初写成 head -1 | grep -c 206,
结果所有带重定向的链接都被判成「不支持分片」,白白退回单线程。
三、下载完记得校验
大文件下载出错不容易发现,尤其是多线程拼接。校验一下更安心:
# SHA256(与官方公布的值对比)
shasum -a 256 ~/Downloads/file.iso
# 如果官方只给了 SHA1
shasum -a 1 ~/Downloads/file.iso
# 查看文件真实类型(扩展名可以骗人)
file ~/Downloads/file.iso
ISO 镜像还可以看卷标和是否可引导:
file win11.iso
# 输出类似:ISO 9660 CD-ROM filesystem data 'XXXX_X64FRE_ZH-CN_DV9' (bootable)
# ↑ 卷标 ↑ 可引导
四、什么时候用哪个
| 场景 | 建议 |
|---|---|
| 大文件、服务器单流限速 | aria2 或 pget,16 线程 |
| 小文件(< 10MB) | 直接 curl / 浏览器 |
| 服务器单流不限速 | 单线程反而更快 |
| 需要断点续传、BT | aria2(pget 不支持) |
| 不想装任何东西 | pget |