PowerShell小技巧之實(shí)現(xiàn)文件下載(類wget)
對(duì)Linux熟悉的讀者可能會(huì)對(duì)Linux通過(guò)wget下載文件有印象,這個(gè)工具功能很強(qiáng)大,在.NET環(huán)境下提到下載文件大多數(shù)人熟悉的是通過(guò)System.Net.WebClient進(jìn)行下載,這個(gè)程序集能實(shí)現(xiàn)下載的功能,但是有缺陷,如果碰上類似于…/scripts/?dl=417這類的下載鏈接將無(wú)法正確識(shí)別文件名,下載的文件通常會(huì)被命名為dl=417這樣古怪的名字,其實(shí)對(duì)應(yīng)的文件名是在訪問(wèn)這個(gè)鏈接返回結(jié)果的HTTP頭中包含的。事實(shí)上微軟也提供了避免這些缺陷的程序集System.Net.HttpWebRequest 和 HttpWebResponse,本文將會(huì)使用這兩個(gè)程序集來(lái)實(shí)現(xiàn)PowerShell版wget的功能。
代碼不怎么復(fù)雜,基本上就是創(chuàng)建HttpWebRequest對(duì)象,設(shè)定UserAgent和CookieContainer以免在遇到設(shè)置防盜鏈的服務(wù)器出現(xiàn)無(wú)法下載的情況。然后通過(guò)HttpWebRequest對(duì)象的GetResponse()方法從http頭中獲取目標(biāo)文件的大小以及文件名,以便能在下載到文件時(shí)提示當(dāng)前下載進(jìn)度,在下載完文件后,列出當(dāng)前目錄下對(duì)應(yīng)的文件。代碼不復(fù)雜,有任何疑問(wèn)的讀者可以留言給我,進(jìn)行交流,下面上代碼:
=====文件名:Get-WebFile.ps1=====
function Get-WebFile {
<# Author:fuhj(powershell#live.cn ,http://fuhaijun.com)
Downloads a file or page from the web
.Example
Get-WebFile http://mirrors.cnnic.cn/apache/couchdb/binary/win/1.4.0/setup-couchdb-1.4.0_R16B01.exe
Downloads the latest version of this file to the current directory
#>
[CmdletBinding(DefaultParameterSetName="NoCredentials")]
param(
# The URL of the file/page to download
[Parameter(Mandatory=$true,Position=0)]
[System.Uri][Alias("Url")]$Uri # = (Read-Host "The URL to download")
,
# A Path to save the downloaded content.
[string]$FileName
,
# Leave the file unblocked instead of blocked
[Switch]$Unblocked
,
# Rather than saving the downloaded content to a file, output it.
# This is for text documents like web pages and rss feeds, and allows you to avoid temporarily caching the text in a file.
[switch]$Passthru
,
# Supresses the Write-Progress during download
[switch]$Quiet
,
# The name of a variable to store the session (cookies) in
[String]$SessionVariableName
,
# Text to include at the front of the UserAgent string
[string]$UserAgent = "PowerShellWget/$(1.0)"
)
Write-Verbose "Downloading '$Uri'"
$EAP,$ErrorActionPreference = $ErrorActionPreference, "Stop"
$request = [System.Net.HttpWebRequest]::Create($Uri);
$ErrorActionPreference = $EAP
$request.UserAgent = $(
"{0} (PowerShell {1}; .NET CLR {2}; {3};
$(if($Host.Version){$Host.Version}else{"1.0"}),
[Environment]::Version,
[Environment]::OSVersion.ToString().Replace("Microsoft Windows ", "Win")
)
$Cookies = New-Object System.Net.CookieContainer
if($SessionVariableName) {
$Cookies = Get-Variable $SessionVariableName -Scope 1
}
$request.CookieContainer = $Cookies
if($SessionVariableName) {
Set-Variable $SessionVariableName -Scope 1 -Value $Cookies
}
try {
$res = $request.GetResponse();
} catch [System.Net.WebException] {
Write-Error $_.Exception -Category ResourceUnavailable
return
} catch {
Write-Error $_.Exception -Category NotImplemented
return
}
if((Test-Path variable:res) -and $res.StatusCode -eq 200) {
if($fileName -and !(Split-Path $fileName)) {
$fileName = Join-Path (Convert-Path (Get-Location -PSProvider "FileSystem")) $fileName
}
elseif((!$Passthru -and !$fileName) -or ($fileName -and (Test-Path -PathType "Container" $fileName)))
{
[string]$fileName = ([regex]'(?i)filename=(.*)$').Match( $res.Headers["Content-Disposition"] ).Groups[1].Value
$fileName = $fileName.trim("\/""'")
$ofs = ""
$fileName = [Regex]::Replace($fileName, "[$([Regex]::Escape(""$([System.IO.Path]::GetInvalidPathChars())$([IO.Path]::AltDirectorySeparatorChar)$([IO.Path]::DirectorySeparatorChar)""))]", "_")
$ofs = " "
if(!$fileName) {
$fileName = $res.ResponseUri.Segments[-1]
$fileName = $fileName.trim("\/")
if(!$fileName) {
$fileName = Read-Host "Please provide a file name"
}
$fileName = $fileName.trim("\/")
if(!([IO.FileInfo]$fileName).Extension) {
$fileName = $fileName + "." + $res.ContentType.Split(";")[0].Split("/")[1]
}
}
$fileName = Join-Path (Convert-Path (Get-Location -PSProvider "FileSystem")) $fileName
}
if($Passthru) {
$encoding = [System.Text.Encoding]::GetEncoding( $res.CharacterSet )
[string]$output = ""
}
[int]$goal = $res.ContentLength
$reader = $res.GetResponseStream()
if($fileName) {
try {
$writer = new-object System.IO.FileStream $fileName, "Create"
} catch {
Write-Error $_.Exception -Category WriteError
return
}
}
[byte[]]$buffer = new-object byte[] 4096
[int]$total = [int]$count = 0
do
{
$count = $reader.Read($buffer, 0, $buffer.Length);
if($fileName) {
$writer.Write($buffer, 0, $count);
}
if($Passthru){
$output += $encoding.GetString($buffer,0,$count)
} elseif(!$quiet) {
$total += $count
if($goal -gt 0) {
Write-Progress "Downloading $Uri" "Saving $total of $goal" -id 0 -percentComplete (($total/$goal)*100)
} else {
Write-Progress "Downloading $Uri" "Saving $total bytes..." -id 0
}
}
} while ($count -gt 0)
$reader.Close()
if($fileName) {
$writer.Flush()
$writer.Close()
}
if($Passthru){
$output
}
}
if(Test-Path variable:res) { $res.Close(); }
if($fileName) {
ls $fileName
}
}
調(diào)用方法,如下:
Get-WebFile http://mirrors.cnnic.cn/apache/couchdb/binary/win/1.4.0/setup-couchdb-1.4.0_R16B01.exe
這里下載couchdb的最新windows安裝包。
執(zhí)行效果如下圖所示:

能夠看到在下載文件的過(guò)程中會(huì)顯示當(dāng)前已下載數(shù)和總的文件大小,并且有進(jìn)度條顯示當(dāng)前下載的進(jìn)度,跟wget看起來(lái)是有些神似了。下載完畢后會(huì)顯示已經(jīng)下載文件的情況。

相關(guān)文章
PowerShell函數(shù)使用正則表達(dá)式驗(yàn)證輸入?yún)?shù)實(shí)例
這篇文章主要介紹了PowerShell函數(shù)使用正則表達(dá)式驗(yàn)證輸入?yún)?shù)實(shí)例,即檢驗(yàn)輸入?yún)?shù)是否符合正則規(guī)則,需要的朋友可以參考下2014-07-07
PowerShell使用正則表達(dá)式查找字符串實(shí)例
這篇文章主要介紹了PowerShell使用正則表達(dá)式查找字符串實(shí)例,主要是對(duì)match運(yùn)算符的使用介紹,需要的朋友可以參考下2014-08-08
Windows Powershell方法(對(duì)象能做什么)
方法定義了一個(gè)對(duì)象可以做什么事情。當(dāng)你把一個(gè)對(duì)象輸出在控制臺(tái)時(shí),它的屬性可能會(huì)被轉(zhuǎn)換成可視的文本。但是它的方法卻不可見(jiàn)。2014-09-09
Powershell讀取本機(jī)注冊(cè)表中的所有軟件關(guān)聯(lián)擴(kuò)展名
這篇文章主要介紹了Powershell讀取本機(jī)注冊(cè)表中的所有軟件關(guān)聯(lián)擴(kuò)展名,本文直接給出實(shí)現(xiàn)代碼,需要的朋友可以參考下2015-03-03
Powershell小技巧之查看安裝的.Net framework版本信息
本文主要介紹了使用powershell查看安裝的.net framework的版本信息,非常簡(jiǎn)單使用,有需要的朋友參考下2014-09-09
PowerShell腳本監(jiān)控文件夾變化實(shí)例
這篇文章主要介紹了PowerShell腳本監(jiān)控文件夾變化實(shí)例,可以監(jiān)控到文件夾內(nèi)新建文件、刪除文件、重命名文件等操作,需要的朋友可以參考下2014-08-08
通過(guò)DNS TXT記錄執(zhí)行powershell
這篇文章主要介紹了通過(guò)DNS TXT記錄執(zhí)行powershell的相關(guān)資料,以及nishang的腳本使用,需要的朋友可以參考下2017-10-10

