PowerShell wget:下载文件的好方法
您是否需要从网络下载文件但讨厌重复点击链接?如果您的工作涉及定期从网络下载文件,您可能希望自动执行该任务。为什么不使用 PowerShell 来下载文件,就像替代 PowerShell wget 一样?
Windows PowerShell 和 PowerShell 附带文件下载功能。使用 PowerShell 下载文件只需了解要使用哪些 cmdlet 和 .NET 类以及如何使用它们。
在本文中,您将了解使用 PowerShell 从网络下载文件的各种方法。
先决条件
由于这是一篇边做边学的文章,因此需要满足一些先决条件才能确保您能够遵循示例。以下是基本要求。
- 运行 Windows 10 或更高版本的计算机。您将在这台计算机上运行本文中介绍的脚本/命令。
Windows PowerShell 5.1 或 PowerShell 7.1(推荐)。
- Windows 10 已包含 Windows PowerShell 5.1。
托管要下载的文件的网站。
- 对于未经身份验证的文件下载,请考虑使用免费的 Tele2 Speedtest 网站。
使用 PowerShell 从 URL 下载文件:四种方法
有四种方法可以使用PowerShell下载不依赖第三方工具的文件。这些都是:
Invoke-WebRequestInvoke-RestMethodStart-BitsTransfer无论您使用这四种方法中的哪一种,使它们发挥作用的逻辑和组件都是相同的。必须有一个指向文件位置的源 URL 和保存下载文件的目标路径。如果网络服务器需要,您还需要输入凭据。
接下来的部分将分别介绍这四种方法。最后,由您决定在使用 PowerShell 下载文件时采用哪种方式。
使用 Invoke-WebRequest 作为 PowerShell wget 替代方案
PowerShell 中下载文件的第一种方法是使用 Invoke-WebRequest cmdlet。也许本文中最常用的 cmdlet Invoke-WebRequest 可以下载 HTTP、HTTPS 和 FTP 链接。
无论源位置是否需要用户登录,Invoke-WebRequest cmdlet 都可以处理带有凭据的请求。
要下载文件,下面的语法显示了实现所需结果所需的最少参数。
Invoke-WebRequest -Uri <source> -OutFile <destination>例如,下面的代码从网站下载名为 10MB.zip 的文件。然后它将下载的文件保存到C:\dload\10MB.zip。您可以复制下面的代码并将其粘贴到您的 PowerShell 会话中进行测试。
# Source file location
$source = 'http://speedtest.tele2.net/10MB.zip'
# Destination to save the file
$destination = 'c:\dload\10MB.zip'
#Download the file
Invoke-WebRequest -Uri $source -OutFile $destination下面的演示显示了在 PowerShell 中运行上述代码后的预期结果。可以看到,文件下载成功。
如果来源在允许访问之前需要身份验证怎么办?例如,下面的代码从用户必须登录的私人网站下载文件。
$source = 'https://mirror.lzex.ml/100MB.zip'
$destination = 'c:\dload\100MB.zip'
Invoke-WebRequest -Uri $source -OutFile $destination然而,由于未经授权的访问,下载失败。
如果需要身份验证,您应使用 -Credential 参数向请求添加凭据。下面代码中的第一行提示您输入凭据(用户名和密码)并将其存储到 $credential 变量中。
$credential = Get-Credential
$source = 'https://mirror.lzex.ml/100MB.zip'
$destination = 'c:\dload\100MB.zip'
Invoke-WebRequest -Uri $source -OutFile $destination -Credential $credential
下面的演示显示了在 PowerShell 中运行上述代码时您期望看到的内容。如您所见,Get-Credential cmdlet 提示了PowerShell 凭据请求。这次,将凭证与 Invoke-WebRequest 一起使用导致下载成功。
相关:使用 PowerShell Get-Credential Cmdlet 和所有凭证
使用 Invoke-WebRequest 时注意解析错误
在 Windows PowerShell 中使用 Invoke-WebRequest 时要记住的一件重要事情是,默认情况下,此 cmdlet 使用 Internet Explorer 引擎来解析数据。在没有安装 Internet Explorer 的计算机上使用 Invoke-WebRequest 时,可能会出现以下错误。
您必须重新发出命令,但这一次,包括 -UseBasicParsing 开关。
Invoke-WebRequest -Uri <source> -OutFile <destination> -UseBasicParsing在 Windows PowerShell 中,您可能会收到错误消息:无法解析响应内容,因为 Internet Explorer 引擎不可用,或者 Internet Explorer 的首次启动配置不完整。指定 UseBasicParsing 参数并重试。
从 PowerShell Core 6.0 开始,Invoke-WebRequest cmdlet 仅使用基本解析。因此,不再需要 -UseBasicParsing 参数。
使用调用 RestMethod
Invoke-RestMethod cmdlet 更多的是关于向 RESTful Web 服务发送 HTTP 或 HTTPS 请求。此 cmdlet 更适合与 REST API(例如 Microsoft Graph API)交互的请求。
当谈到直接从网络下载文件时,Invoke-RestMethod 是一个很好的竞争者。不要被欺骗而产生其他想法。当用于从直接 Web 链接下载文件时,使用 Invoke-RestMethod 和 Invoke-WebRequest 之间没有太大区别。
使用 Invoke-RestMethod 下载文件
要使用 Invoke-RestMethod 下载文件,请使用以下语法。您会注意到该命令使用与 Invoke-WebRequest 相同的参数。
Invoke-RestMethod -Uri <source> -OutFile <destination>在下面的示例代码中,文件是从 $source 变量中的 URL 值下载的。然后,保存到 $destination 变量中定义的路径。
$source = 'http://speedtest.tele2.net/10MB.zip'
$destination = 'c:\dload\10MB.zip'
Invoke-RestMethod -Uri $source -OutFile $destination如果源需要身份验证,您可以使用 -Credential 参数传递凭据。下面的示例提示输入凭据并将其存储到 $credential 变量中。然后,$credential 变量的值将传递给 -Credential 参数。
此外,由于文件链接是 HTTP 源而不是 HTTPS,这意味着您正在发送未加密的身份验证。通常,出于安全考虑,您应该避免使用 HTTP 源。但如果您必须使用 HTTP 源,则需要将 -AllowUnencryptedAuthentication 开关添加到命令中。
$credential = Get-Credential
$source = 'http://speedtest.tele2.net/10MB.zip'
$destination = 'c:\dload\10MB.zip'
Invoke-RestMethod -Uri $source -OutFile $destination -Credential $credential -AllowUnencryptedAuthentication
使用起始位传输
Start-BitsTransfer 专为在客户端和服务器计算机之间传输文件而设计。此 PowerShell cmdlet 依赖于 Windows 操作系统本机的后台智能传输服务 (BITS)。
由于 Start-BitsTransfer 需要 BITS 才能工作,这意味着此 cmdlet 在非 Windows 计算机上不可用。另一方面,Start-BitsTransfer 享有 BITS 本身的优势。其中一些好处是:
- 网络带宽和使用意识。
- 中断处理(恢复、自动恢复、暂停等)
- 下载多个文件作为后台作业。
- 能够设置下载作业优先级。
下载文件
在 PowerShell 中使用 Start-BitsTransfer 下载文件的基本方法是指定源和目标。使用下面的脚本,您只需根据您的要求更改 $source 和 $destination 值。
$source = 'http://speedtest.tele2.net/100MB.zip'
$destination = 'c:\dload\100MB.zip'
Start-BitsTransfer -Source $source -Destination $destination从下面的演示中可以看到,文件被下载到路径c:\dload\100MB.zip。
假设未指定目的地,
Start-BitsTransfer将下载文件并将其保存到当前工作目录。例如,如果您从 C:\dload 运行Start-BitsTransfer,文件将下载到同一目录。
对于需要身份验证的下载,Start-BitsTransfer 有一个 -Credential 参数,该参数接受 PSCredential 对象。
下载多个文件
为了演示下载多个文件,您需要创建一个包含两列的 CSV 文件。将文件命名为 filelist.txt。第一列应包含源链接,而第二列必须包含目标路径。文件内容如下所示。
# source,destination
http://speedtest.tele2.net/1MB.zip,c:\dload\1MB.zip
http://speedtest.tele2.net/10MB.zip,c:\dload\10MB.zip
http://speedtest.tele2.net/100MB.zip,c:\dload\100MB.zip相关:使用 Import-Csv 在 PowerShell 中管理 CSV 文件
CSV 文件准备就绪后,使用以下命令开始下载文件。该命令使用 Import-Csv 导入 CSV 文件,并将内容传递给 Start-BitsTransfer。
Import-Csv .\filelist.csv | Start-BitsTransfer请参阅下面的演示,了解上面的代码是如何工作的。如您所见,下载开始,并且您会看到下载进度。下载过程中不会出现 PowerShell 提示符。
假设您想将下载过程作为后台作业启动。为此,您只需在 Start-BitsTransfer 命令末尾添加 -Asynchronous 开关即可。
Import-Csv .\filelist.csv | Start-BitsTransfer -Asynchronous最初,每个作业的状态将显示“正在连接”。下面的屏幕截图显示了每个文件下载的作业 ID。
现在您已经开始下载过程,您需要检查下载是否已完成。要检查下载作业状态,请使用 Get-BitsTransfer cmdlet。如下所示,下载作业的状态已更改为已传输。
使用 WebClient 类和 HttpClient 类 (.NET Framework)
PowerShell 基于 .NET,其性质使其能够利用 .NET 本身的强大功能。您可以在 PowerShell 中使用两个 .NET 类来下载文件; WebClient 和 HttpClient。
如果您想以更多的开发和技术方式了解这两个 .NET 类,您可以从 → 何时使用 WebClient、HttpClient 和 HttpWebRequest 开始。 在下一节中,您将学习如何在 PowerShell 中使用 WebClient 和 HttpClient 从网络下载文件。
使用 System.Net.WebClient 下载文件
要使用 WebClient 类,您需要将一个对象启动为 System.Net.WebClient **类型。在下面的示例中,$webClient 是新的 System.Net.WebClient 对象。然后,使用 DownloadFile() 方法开始从源下载文件。
相关:使用 PowerShell 数据类型加速器加速编码
请复制下面的代码并在 PowerShell 会话中运行它进行测试。请注意,除非出现错误,否则您不会在屏幕上看到任何进度或输出。但是,在下载完成之前,PowerShell 提示符将被锁定。
# Define the source link and destination path
$source = 'http://speedtest.tele2.net/10MB.zip'
$destination = 'c:\dload\10MB.zip'
# Create the new WebClient
$webClient = [System.Net.WebClient]::new()
# Download the file
$webClient.DownloadFile($source, $destination)如果源需要身份验证才能允许文件下载,您可以使用下面的代码。第一行提示输入凭据并将其存储到 $credentials 变量中。然后,$credential 的值将包含在文件下载请求中。
# Prompt for username and password
$credentials = Get-Credential
$source = 'http://speedtest.tele2.net/10MB.zip'
$destination = 'c:\dload\10MB.zip'
# Create the new WebClient
$webClient = [System.Net.WebClient]::new()
# Add the credential
$webClient.Credentials = $credentials
# Download the file
$webClient.DownloadFile($source, $destination)
根据此 Microsoft 文档:“我们不建议您使用 WebClient 类进行新开发。相反,请使用 System.Net.Http.HttpClient 类。”
看起来WebClient类已经过时了,微软支持的新类是HttpClient类。不过别担心。下一节将讨论如何使用 PowerShell 中的 HttpClient 类从网络下载文件。
使用 System.Net.Http.HttpClient 下载文件
与 WebClient 类一样,您需要首先创建 System.Net.Http.HttpClient。使用下面的代码将文件从 $source 下载到 $destination。参考每行上面的注释就可以知道每行代码的作用。
下面的代码是实时的,您可以通过在 PowerShell 会话中运行它来测试它。
# Set the source and destination
$source = 'http://speedtest.tele2.net/10MB.zip'
$destination = 'c:\dload\10MB.zip'
# Create the HTTP client download request
$httpClient = New-Object System.Net.Http.HttpClient
$response = $httpClient.GetAsync($source)
$response.Wait()
# Create a file stream to pointed to the output file destination
$outputFileStream = [System.IO.FileStream]::new($destination, [System.IO.FileMode]::Create, [System.IO.FileAccess]::Write)
# Stream the download to the destination file stream
$downloadTask = $response.Result.Content.CopyToAsync($outputFileStream)
$downloadTask.Wait()
# Close the file stream
$outputFileStream.Close()在下载文件需要身份验证的情况下,您需要将凭据添加到 HttpClient 对象。要在文件下载请求中包含凭据,请创建一个新的 System.Net.Http.HttpClientHandler 对象来存储凭据。
您可以复制下面的代码并在PowerShell中运行进行测试。或者您也可以将其作为 PowerShell 脚本运行。在此示例中,代码保存为 download-file.ps1。
# Set the source and destination
$source = 'http://speedtest.tele2.net/10MB.zip'
$destination = 'c:\dload\10MB.zip'
# Prompt for credentials
$credentials = Get-Credential
# Create the HTTP client download request with credentials
$handler = New-Object System.Net.Http.HttpClientHandler
$handler.Credentials = $credentials
$httpClient = New-Object System.Net.Http.HttpClient($handler)
$response = $httpClient.GetAsync($source)
$response.Wait()
# Create a file stream to pointed to the output file destination
$outputFileStream = [System.IO.FileStream]::new($destination, [System.IO.FileMode]::Create, [System.IO.FileAccess]::Write)
# Stream the download to the destination file stream
$downloadTask = $response.Result.Content.CopyToAsync($outputFileStream)
$downloadTask.Wait()
# Close the file stream
$outputFileStream.Close()下面的演示显示了运行 PowerShell 脚本下载文件时的结果。
一开始,该目录中只有脚本文件。系统会提示输入用户名和密码。然后,脚本继续下载文件。下载文件后,您可以看到新文件现在位于目标目录中。
结论
Windows PowerShell 和 PowerShell Core 具有下载文件的内置功能,可作为 PowerShell wget 的替代品!无论是下载受密码保护的源文件、单个文件还是多个文件,您都可以使用 PowerShell 方式。
本文介绍的文件下载方法适用于 Windows PowerShell 和 PowerShell Core。这意味着这些方法适用于 Windows 和非 Windows 系统,但不包括 Start-BitsTransfer。
由于 PowerShell 不仅仅是一个命令提示符,因此您可以将所学到的内容转化为脚本。对您来说,这意味着自动化的机会。不再需要手动复制 URL、单击链接和等待下载。







