Skip to content

Instantly share code, notes, and snippets.

@gravejester
Created October 7, 2014 11:24
Show Gist options
  • Save gravejester/f464ef9eaab17d30ff3b to your computer and use it in GitHub Desktop.
Save gravejester/f464ef9eaab17d30ff3b to your computer and use it in GitHub Desktop.
Download a file from the internet.
function Get-WebFile {
<#
.SYNOPSIS
Download a file from the internet.
.DESCRIPTION
Download a file from the internet.
.PARAMETER Url
URL of file being downloaded
.PARAMETER TargetPath
Target path where the downloaded file will be saved. Defaults to the current folder.
.PARAMETER Timeout
Request timeout in milliseconds. Default is 100000.
.EXAMPLE
Get-WebFile http://some.server.com/file_to_download.zip
Description
-----------
Download file_to_download.zip to the current folder
.NOTES
Name: Get-WebFile
Author: Øyvind Kallstad
Date: 26.02.2014
Version: 1.0
#>
[CmdletBinding()]
param(
[Parameter(Mandatory = $true, Position = 0)]
[string]$Url,
[Parameter(Position = 1)]
[ValidateScript({Test-Path $_ -PathType Container})]
[string]$TargetPath = (Get-Location).Path,
[Parameter()]
[int]$Timeout
)
try{
$target = Join-Path -Path $TargetPath -ChildPath (Split-Path -Leaf $url)
# Create a web request object.
$request = [System.Net.WebRequest]::Create($url)
# Configure timeout if specified. Otherwise default value will be used.
if($Timeout){
$request.Timeout = $Timeout
Write-Verbose "Request timeout set to $Timeout milliseconds"
}
# Get a response from the server
$response = $request.GetResponse()
if(-not($response.Server)){
$server = ($response.ResponseUri.ToString()).Split("/")[2]
}
else{
$server = $response.Server
}
# Check that the response is ok before continuing.
if($response.StatusCode -ne 'OK'){
Write-Warning "A problem occured. The server responded with the following code: $($response.StatusCode)"
break
}
else{
Write-Verbose "Got a response back from $server"
}
# Get a response stream from the server
$responseStream = $response.GetResponseStream()
# Check that we are able to read the stream before continuing
if(-not($responseStream.CanRead)){
Write-Warning 'Unable to read from server'
break
}
# Set up a target stream. This will also create the destination file.
$targetStream = New-Object -TypeName System.IO.FileStream -ArgumentList $target, Create
Write-Verbose "Successfully created $target"
# Set up a small buffer and start to read.
$buffer = New-Object byte[] 10KB
$read = $responseStream.Read($buffer,0,$buffer.length)
# Take a note of the total downloaded bytes.
$downloadedBytes = $read
# As long as there are bytes that have have been read...
while($read -gt 0){
# ... write data to the destination file
$targetStream.Write($buffer,0,$read)
# New read
$read = $responseStream.Read($buffer,0,$buffer.length)
# Recalculate the total downloaded bytes
$downloadedBytes = $downloadedBytes + $read
# Calculate percent complete
$percentComplete = (($downloadedBytes/$response.ContentLength))*100
# Write progress bar
Write-Progress -Activity "Downloading '$(Split-Path -Leaf $url)' from $($server)" -Status "Downloaded $($downloadedBytes) of $($response.ContentLength) bytes." -PercentComplete $percentComplete
}
Write-Progress -Activity "Finished downloading file '$(Split-Path -Leaf $url)'" -Completed
Write-Verbose 'Finished downloading file'
# Let's clean up
$targetStream.Flush()
$targetStream.Close()
$targetStream.Dispose()
$responseStream.Close()
$responseStream.Dispose()
Write-Verbose 'Finished closing connections'
}
catch{
# Catching any exceptions
Write-Warning $_.Exception.Message
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment