Skip to content

Instantly share code, notes, and snippets.

@dindoliboon
Last active May 13, 2019 15:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dindoliboon/f378b41ed09a820d10407466a503161e to your computer and use it in GitHub Desktop.
Save dindoliboon/f378b41ed09a820d10407466a503161e to your computer and use it in GitHub Desktop.
Download files in Nano Server.
<#
.DESCRIPTION
Downloads a file from the specified website.
.EXAMPLE
Downloads Jetty 9.3.20.
Get-WebFile -Uri 'http://central.maven.org/maven2/org/eclipse/jetty/jetty-distribution/9.3.20.v20170531/jetty-distribution-9.3.20.v20170531.zip' -OutFile 'C:\jetty-distribution-9.3.20.v20170531.zip'
.EXAMPLE
Downloads Oracle Server JRE 8u131 and verifies hash.
Get-WebFile -Uri 'http://download.oracle.com/otn-pub/java/jdk/8u131-b11/d54c1d3a095b4ff2b6607d096fa80163/server-jre-8u131-windows-x64.tar.gz' -OutFile 'C:\server-jre-8u131-windows-x64.tar.gz' -Cookie 'oraclelicense=accept-securebackup-cookie;' -Hash '1806EBE235EAB2B21C893ACBF0B287A392CE6B5EDFEA3286FC8FF7D6DEFB19CB'
.OUTPUTS
Boolean. True if successful and if specified, hash value matches. Otheriwse, False is returned.
.NOTES
Tested on Windows Server 2016, Nano Server.
[Environment]::OSVersion
Platform Version
-------- -------
Win32NT 10.0.14393.0
$PSVersionTable
Name Value
---- -----
PSVersion 5.1.14393.1000
SerializationVersion 1.1.0.1
PSEdition Core
PSRemotingProtocolVersion 2.3
CLRVersion
BuildVersion 10.0.14393.1000
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0...}
WSManStackVersion 3.0
Code from the following websites:
https://stackoverflow.com/questions/20661652/progress-bar-with-httpclient
https://github.com/dotnet/corefx/issues/6849
https://stackoverflow.com/a/13287224
https://serverfault.com/a/788951
#>
function Get-WebFile ($Uri, $OutFile, $Cookie, $Hash, $Algorithm='SHA256', $BufferSize=64KB)
{
$ret = $false
if ((Test-Path -Path $OutFile) -eq $false)
{
Add-Type -AssemblyName System.Net.Http
$handler = New-Object -TypeName System.Net.Http.HttpClientHandler -Property @{UseCookies = $false}
$client = New-Object -TypeName System.Net.Http.HttpClient($handler) -Property @{BaseAddress = $Uri}
if ($null -ne $Cookie -and $Cookie.Length -gt 0)
{
$client.DefaultRequestHeaders.Add('Cookie', $Cookie)
}
$client.GetAsync($Uri, [System.Net.Http.HttpCompletionOption]::ResponseHeadersRead) |% {
$_.Wait()
$response = $_.Result
Write-Verbose -Message "Status: $($response.StatusCode)"
if ($response.StatusCode -eq 'Redirect')
{
$ret = Get-WebFile -Uri $response.Headers.Location.OriginalString -OutFile $OutFile -Cookie $Cookie -BufferSize $BufferSize
}
elseif ($response.StatusCode -eq 'OK' -and $null -ne $response.Content.Headers.ContentLength)
{
$contentStream = $response.Content.ReadAsStreamAsync()
$contentStream.Wait()
$totalRead = 0
$totalReads = 0
$buffer = New-Object -TypeName byte[] -ArgumentList $BufferSize
$isMoreToRead = $true
$downloadedFileStream = New-Object -TypeName System.IO.FileStream($OutFile, [System.IO.FileMode]::Create, [System.IO.FileAccess]::Write, [System.IO.FileShare]::None, $BufferSize, $true)
do
{
$read = $contentStream.Result.ReadAsync($buffer, 0, $BufferSize)
if ($read.Result -eq 0)
{
$isMoreToRead = $false
$downloadedFileStream.Close()
}
else
{
$downloadedFileStream.WriteAsync($buffer, 0, $read.Result) | Out-Null
$totalRead += $read.Result
$totalReads += 1
$percentage = $totalRead / $response.Content.Headers.ContentLength * 100
Write-Progress -Activity 'Writing web request' -status "Writing request stream... (Number of bytes written: $totalRead/$($response.Content.Headers.ContentLength)) = $percentage%" -PercentComplete $percentage
}
} while ($isMoreToRead)
$ret = $true
}
else
{
Write-Error -Message 'Unable to continue. No redirect, or OK status with file size returned.'
}
}
$client.Dispose()
$client = $null
$handler.Dispose()
$handler = $null
}
if ($null -ne $Hash -and $Hash.Length -gt 0)
{
$fileHash = Get-FileHash -Path $OutFile -Algorithm $Algorithm
if ($fileHash.Hash -eq $Hash)
{
$ret = $true
}
else
{
Write-Error -Message "File hash does not match. Expected [$Hash], got [$($fileHash.Hash)]."
$ret = $false
}
}
$ret
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment