Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Ok, so the easiest way (that I know of) to download files in powershell from the internet is to use the .net WebClient. The simple way I started with was the two liner:
$client = New-Object "System.Net.WebClient"
$client.DownloadFile("https://somesite.com/largefile.zip","c:\temp\largefile.zip"
However I was working on a script that required some pretty large files to be downloaded, and using the DownloadFile method has no progress indicator. I figured some users might thing the program died. So I decided to create a method that still uses the webclient to download the files, however give a status of where it is in the download. Here is what I came up with, hopefully someone else will find it useful.
function downloadFile($url, $targetFile)
{
"Downloading $url"
$uri = New-Object "System.Uri" "$url"
$request = [System.Net.HttpWebRequest]::Create($uri)
$request.set_Timeout(15000) #15 second timeout
$response = $request.GetResponse()
$totalLength = [System.Math]::Floor($response.get_ContentLength()/1024)
$responseStream = $response.GetResponseStream()
$targetStream = New-Object -TypeName System.IO.FileStream -ArgumentList $targetFile, Create
$buffer = new-object byte[] 10KB
$count = $responseStream.Read($buffer,0,$buffer.length)
$downloadedBytes = $count
while ($count -gt 0)
{
[System.Console]::CursorLeft = 0
[System.Console]::Write("Downloaded {0}K of {1}K", [System.Math]::Floor($downloadedBytes/1024), $totalLength)
$targetStream.Write($buffer, 0, $count)
$count = $responseStream.Read($buffer,0,$buffer.length)
$downloadedBytes = $downloadedBytes + $count
}
"`nFinished Download"
$targetStream.Flush()
$targetStream.Close()
$targetStream.Dispose()
$responseStream.Dispose()
}
This would be used like
downloadFile "https://somesite/largefile.zip" "c:\temp\largefile.zip"
Comments
Anonymous
December 20, 2012
Hey, thanks! Good function. I've modified the code a bit, so that it would support the 'Write-Progress' cmdlet: function DownloadFile($url, $targetFile) { $uri = New-Object "System.Uri" "$url" $request = [System.Net.HttpWebRequest]::Create($uri) $request.set_Timeout(15000) #15 second timeout $response = $request.GetResponse() $totalLength = [System.Math]::Floor($response.get_ContentLength()/1024) $responseStream = $response.GetResponseStream() $targetStream = New-Object -TypeName System.IO.FileStream -ArgumentList $targetFile, Create $buffer = new-object byte[] 10KB $count = $responseStream.Read($buffer,0,$buffer.length) $downloadedBytes = $count while ($count -gt 0) { $targetStream.Write($buffer, 0, $count) $count = $responseStream.Read($buffer,0,$buffer.length) $downloadedBytes = $downloadedBytes + $count Write-Progress -activity "Downloading file '$($url.split('/') | Select -Last 1)'" -status "Downloaded ($([System.Math]::Floor($downloadedBytes/1024))K of $($totalLength)K): " -PercentComplete ((([System.Math]::Floor($downloadedBytes/1024)) / $totalLength) * 100) } Write-Progress -activity "Finished downloading file '$($url.split('/') | Select -Last 1)'" $targetStream.Flush() $targetStream.Close() $targetStream.Dispose() $responseStream.Dispose() }Anonymous
June 10, 2013
Awesome with the Write-Progress addition! Thx lime!Anonymous
September 22, 2013
Nice bit of code that, thanks guys!Anonymous
September 08, 2014
Problem with the code when the download file is less than 1024 bytes. I corrected by doing an If/else statement that checks for file length less than 1024: $responseContentLength = $response.get_ContentLength() if(-not ($responseContentLength -lt 1024)) { $totalLength = [System.Math]::Floor($response.get_ContentLength()/1024) } else { $totalLength = [System.Math]::Floor(1024/1024) }Anonymous
August 04, 2015
I'm getting an exception error You cannot call a method on a null-valued expression. At line:18 char:9
- $targetStream.Write($buffer, 0, $count)
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidOperation: (:) [], RuntimeException + FullyQualifiedErrorId : InvokeMethodOnNull Exception setting "CursorLeft": "The handle is invalid. " At line:16 char:9
- [System.Console]::CursorLeft = 0
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (:) [], SetValueInvocationException + FullyQualifiedErrorId : ExceptionWhenSetting