You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何复现Invoke-WebRequest在Win11 24H2/PowerShell5.1中的部分下载问题?

关于PowerShell Invoke-WebRequest部分下载问题的解答

一、如何复现部分下载场景

要复现生成不完整文件的情况,可以尝试以下操作:

  • 模拟服务器中途断开:用本地HTTP服务器(比如Python的http.server)托管大文件,下载过程中强行终止服务器进程。PowerShell 5.1的Invoke-WebRequest可能不会检测到异常,直接保留已下载的部分内容。
  • 限速后中断传输:通过Windows QoS策略限制下载带宽至极低,在下载进行到一半时手动断开网络。部分场景下,客户端会将已接收数据写入文件,且不会触发错误。
  • 构造不完整响应接口:编写简单Web接口,仅返回文件前N字节就关闭连接,Invoke-WebRequest会将已接收内容写入OutFile且不抛出错误。

二、Invoke-WebRequest的错误行为与错误码

在PowerShell 5.1中,Invoke-WebRequest的错误抛出逻辑分场景:

  • 网络中断/超时:会抛出终止错误,对应WinHTTP错误码,比如ERROR_WINHTTP_TIMEOUT(12002)、ERROR_WINHTTP_CANNOT_CONNECT(12029)等。
  • 服务器中途断开返回不完整数据:不会抛出终止错误,会将已接收数据写入文件,响应对象StatusCode可能仍为200,但ContentLength与实际文件大小不匹配。
  • HTTP错误(4xx/5xx):会抛出终止错误,可通过$_.Exception.Response.StatusCode获取对应HTTP状态码。

三、避免此类问题的改进方案

针对原脚本仅检查文件存在的缺陷,可从以下维度优化:

1. 校验文件大小

下载后对比本地文件大小与服务器返回的Content-Length:

$ProgressPreference = 'SilentlyContinue'
$tries = 0
$targetPath = "C:\Recovery\OEM\Agent.msi"
$uri = "https://abc.xyz.com/path/Agent.msi"

do {
    if ($tries -gt 0) {
        Start-Sleep -Seconds ($tries*5)
    }
    try {
        # 获取响应头确认预期文件大小
        $response = Invoke-WebRequest -Uri $uri -Method Head -ErrorAction Stop
        $expectedSize = [long]$response.Headers['Content-Length']
        
        # 执行下载
        Invoke-WebRequest -Uri $uri -OutFile $targetPath -ErrorAction Stop
        
        # 校验文件大小
        $actualSize = (Get-Item $targetPath).Length
        if ($actualSize -eq $expectedSize) {
            break # 下载成功,退出循环
        } else {
            Write-Warning "文件大小不匹配:预期$expectedSize字节,实际$actualSize字节"
            Remove-Item $targetPath -Force # 删除不完整文件
        }
    }
    catch {
        Write-Warning "下载失败: $_"
        # 清理可能存在的不完整文件
        if (Test-Path $targetPath) {
            Remove-Item $targetPath -Force
        }
    }
    $tries++
} while ($tries -lt 5)

2. 使用哈希校验

如果服务器提供文件哈希值(如SHA256),下载后计算本地文件哈希对比:

# 假设服务器提供的SHA256哈希
$expectedHash = "示例哈希值"

# 计算本地文件哈希
$actualHash = (Get-FileHash -Path $targetPath -Algorithm SHA256).Hash
if ($actualHash -ne $expectedHash) {
    Write-Warning "文件校验失败"
    Remove-Item $targetPath -Force
}

3. 强制错误终止行为

在Invoke-WebRequest命令中添加-ErrorAction Stop,确保大部分网络错误进入catch块,避免静默失败。

4. 改用.NET类实现下载

PowerShell 5.1的Invoke-WebRequest对不完整响应处理较宽松,可直接使用.NET的WebClient或HttpClient类,检测更严谨:

$client = New-Object System.Net.WebClient
try {
    $client.DownloadFile($uri, $targetPath)
} catch {
    Write-Warning "下载失败: $_"
    if (Test-Path $targetPath) { Remove-Item $targetPath -Force }
} finally {
    $client.Dispose()
}

内容的提问来源于stack exchange,提问作者Emilio Garcia

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 21:42:50