在 Windows 终端里执行 curl -H \Authorization: Basic MDA2Rw== [https://www.baidu.com/1.zip](https://www.baidu.com/1.zip) -L -o C:\temp\file.zip --verbose时,光标停留在一行* Connection #0 to host [www.baidu.com](http://www.baidu.com/) left intact,随后得到一个无法解压的 zip。这一现象乍看像网络故障,其实它背后牵涉到 HTTP 重定向、连接复用、响应完整性校验以及 Windows shell 对路径与字符的处理。下文将沿着一次典型下载动作的时间线,逐段剖析信息流与控制流,找出压缩包损坏的真正原因,并给出可验证的修复方案。

连接生命周期与 curl 的 verbose 输出

  • libcurl 在建立 TCP 连接后,向终端写入 * Trying <ip>…* Connected to <host> (ip) 等行,它们只是日志而非错误,方便定位握手阶段的瓶颈。([stackoverflow.com](https://stackoverflow.com/questions/55310318/how-to-fix-connection-0-to-host-left-intact-in-php?utm_source=chatgpt.com “How to fix “Connection #0 to host left intact” in PHP”? - Stack Overflow"), [stackoverflow.com](https://stackoverflow.com/questions/61880928/what-does-connection-0-to-host-example-com-left-intact-mean?utm_source=chatgpt.com “what does “* Connection #0 to host example.com left intact” mean?”))

  • 当后续请求仍可能复用相同 socket 时,libcurl 会记录 * Connection #0 to host <name> left intact。这句话表示句柄里的连接对象没有被立即关闭,而被放回连接池等待复用;如果命令一次只取一个 URL,这条信息可忽略,因为进程结束时操作系统仍会回收 socket。([stackoverflow.com](https://stackoverflow.com/questions/61880928/what-does-connection-0-to-host-example-com-left-intact-mean?utm_source=chatgpt.com “what does “* Connection #0 to host example.com left intact” mean?”), curl.se)

  • 该提示本身不会导致 zip 损坏;真正的危险在于:若服务器返回非预期内容(例如 HTML 报错页),curl 仍然会把字节流写进 file.zip,Windows 解压器再据此报错。(serverfault.com, forum.dfinity.org)

重定向与授权:两条暗线交织

HTTP 3xx 链条与 -L

浏览器或 curl 遇到 30x 响应就会跟随 Location 头发起下一跳请求。手动指定 -L 能让 curl 自动完成跳转。若跳转目标并非真实 zip,而是登陆页或 403 提示,结果写盘仍是 HTML。(stackoverflow.com, stackoverflow.com)

Basic Authorization 与失效 token

你在命令里硬编码了 Authorization: Basic MDA2Rw==;若该 token 仅被第一跳接受,而重定向后的域名、路径或协议不同,后续跳转可能丢失 Authorization,导致目标服务器改用匿名模式返回错误页。Stack Overflow 上多次出现 curl -H \Authorization: …`` 却下载到登陆页 HTML 的案例,即因重定向剥离了授权头。(stackoverflow.com, [community.atlassian.com](https://community.atlassian.com/forums/Bamboo-questions/API-response-contains-quot-Connection-0-bamboo-lt-companyname-gt/qaq-p/2002844?utm_source=chatgpt.com "Solved: API response contains “* Connection #0 bamboo.<com…”))

为什么到手的 zip 打不开

  1. 文件内容为 HTML
    打开 file.zip 以文本方式查看,若首行是 <!DOCTYPE html> 或包含 <html>,即可判定这是错误页而非二进制 zip。([unix.stackexchange.com](https://unix.stackexchange.com/questions/686378/curl-downloads-zip-file-as-ascii-text-zipfile-is-not-corrupted?utm_source=chatgpt.com ““curl” downloads .zip file as ASCII text (zipfile is not corrupted!)”), stackoverflow.com)

  2. 下载被截断
    某些 CDN 会在请求体超过阈值时中断连接;又因为你没有 --retry--continue-at, libcurl 直接写一个半截文件到磁盘。下一次调用 7-Zip 时解压器会提示 Unexpected end of archive。(curl.se)

  3. Windows shell 字符转义
    在 PowerShell 中,把路径包进双引号时若含有反斜杠结尾,可能被解释成转义符;C:\temp\file.zip 没问题,但若用户改写为 C:\temp\new\file.zip`` 会触发转义,生成空文件。(askubuntu.com)

逐步定位与自我验证

检查 HTTP 头与响应

curl -H `Authorization: Basic MDA2Rw==` https://www.baidu.com/1.zip \
     -L -w `\nHTTP_CODE=%{http_code}\nREDIR=%{redirect_url}\nSIZE=%{size_download}\n` \
     -o C:\temp\file.zip --verbose --fail

  • --fail 一旦最终响应码≥400 就退出并返回 22,避免把错误页写进 zip。(superuser.com, stackoverflow.com)

  • -w 让 curl 在完成后打印 HTTP 码、最终 URL 与实际下载字节数;如果看到 HTTP_CODE=200SIZE 明显小于 Content-Length,说明下载被截断。

对比响应类型

curl -I -H `Authorization: Basic MDA2Rw==` https://www.baidu.com/1.zip

  • 期望得到 Content-Type: application/zip;若返回 text/html,说明服务端并未输出二进制文件,而是跳转或错误页。(stackoverflow.com)

校验文件哈希

Get-FileHash C:\temp\file.zip -Algorithm MD5

将输出与服务器提供的 MD5 校验和对比即可判定完整性。

保障完整下载的几条实践

  • --remote-name 搭配 --remote-header-name,让 curl 依据 Content-Disposition 自动定名,减少误写入路径的机会。

  • 保留授权头穿越重定向:添加 --location-trusted 让 curl 在每次跳转时保留机密头部;或者把 token 放进 URL 查询串以规避头部丢失(前提是后端允许)。

  • 断点续传与重试--retry 3 --retry-delay 2 --continue-at - 在网络抖动场景下能显著降低损坏概率。

  • 确认 MIME 与大小:脚本里解析 Content-TypeContent-Length,不匹配就立刻 rm file.zip && exit 1

  • *Windows 与 nix 行为差异:在 CMD 用 ^ 转义,在 PowerShell 用 " 反引号` 转义参数,避免路径被截断。(devops.stackexchange.com)

参考脚本范例(可直接运行)

$Url      = 'https://www.baidu.com/1.zip'
$Token    = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes('user:pass'))
$OutFile  = 'C:\temp\file.zip'
$Header   = "Authorization: Basic $Token"

$retry    = 0
do {
    $retry++
    curl -H "`$Header" $Url -L --location-trusted --fail --retry 3 `
         --retry-delay 2 --connect-timeout 10 `
         --output "$OutFile.part"

    if ($LASTEXITCODE -eq 0) {
        Move-Item "$OutFile.part" $OutFile -Force
        $hash = (Get-FileHash $OutFile -Algorithm SHA256).Hash
        Write-Host "Download succeeded, SHA256=$hash"
        break
    } else {
        Write-Host "Attempt $retry failed, retrying…"
    }
} until ($retry -ge 3)

上述脚本:

  • 使用 $OutFile.part 作为临时文件,失败时不会污染旧文件;

  • --location-trusted 保留 Authorization 直至最后一跳;

  • 利用 Get-FileHash 即时校验确保 zip 完整。

结语

Connection #0 to host … left intact 只是 curl 的常规告知,并不代表失败;真正导致压缩包损坏的根源,在于重定向过程中鉴权头丢失、错误页被当作 zip 写盘、或下载被意外中断。遵循上文五条实践,加上 --fail--retry、哈希校验等防御措施,可以让任何自动化脚本都能在高延迟或者跳转繁多的网络环境中安全下载二进制文件。

Logo

这里是“一人公司”的成长家园。我们提供从产品曝光、技术变现到法律财税的全栈内容,并连接云服务、办公空间等稀缺资源,助你专注创造,无忧运营。

更多推荐