Writing Chef Recipes has taken allot of my time recently. And for better or worse, 90% of the recipes need to be what we are calling ‘Platform Agnostic’ – That is, they need to be able to run on both Red Hat Enterprise Linux (RHEL) & Windows Kernel version 6.1 or greater (So, Windows 7 onward). This has had its challenges and when one platform is easy; the other tends to not be. One example is getting files from an HTTP(s) URL. Linux has multiple options depending on what you are trying to achieve (wget, curl), Windows also some options, but I wouldn’t call them straight forward. This is what has brought me to writing this latest function – Get-WebFile – Or realistically – wget for windows.
A few things to note:
- I am using the comment based help for this function (as I said I would moving forward)
- The functionaility is no where near as full as wget – But we can build this out as needed, so I won’t be stressing (yet)
- I am using the correct naming convention for a Powershell function (incidentally I remember this by the fact the commands are all Verb-Noun, or “Action (to an) Object”. Verbs are the ones that Powershell really complains about). Here are the “approved verbs'” for Powershell
This uses the .NET class System.Net.WebClient to download the file using the DownloadFile method (Who would’ve guessed) – The Microsoft documentation is found here – And this will come in handy in the future as we want to expand the functionally of this function. I can see that there is a DownloadFileAsync method in there. This could be good to fire off multiple downloads and have them concurrently download (More on that later I reckon, but that can be another post).
So, if you can read the function, it has:
- 2 Parameters
- $URL – The lcoation of the file to download
- $Output – The path/filename to output the download to – Defaults to the original filename and outputs to the CWD (Current working directory)
- Wraps up around the System.Net.WebClient .NET class
- Uses the Get-Time so we can output a total amount of time the down load took
- This should be expanded to give an average speed as well ($a = file size, $b = Time taken – So the calculation would be $a/$b = (Average speed) – But that ins’t a requirement just at this stage – Another post I reckon? 😀
function Get-Webfile {
<#
.SYNOPSIS
Downloads a file from a URL and outputs it to a location
.DESCRIPTION
This function uses the System.Net.WebClient to download a file from an HTTP(S) URL.
.NOTES
Name : Get-Webfile
Author : Sean Vucich
Version : 0.1
DateCreated: 2017-03-31
DateUpdated: 2017-03-31
Blog : https://1024hobbytes.com/
.LINK
https://1024hobbytes.com/
.EXAMPLE
To download a file from the location "http://example.com/myfile.txt" to the current working dir named after the original file downloaded Get-Webfile -URL "http://example.com/myfile.txt"
#>
param(
[parameter(Mandatory=$true)]$URL,
[parameter(Mandatory=$false)]$output=$null
)
# Get the current time for a nice little out put to console at the end of the download
$start_time=Get-Date
# This is just incase you didn't supply an output - This will just assume you want to
# output to the current dir naming the file based on the orignal URL file name
if ($output -eq $null)
{
$spliturl = $url.split('/')
$output = $spliturl[-1]
}
(New-Object System.Net.WebClient).DownloadFile($url, $output)
Write-Output "Time taken: $((Get-Date).Subtract($start_time).Seconds) second(s)"
}
In action!
Now, how does it all look in action? Well, either give it a go, or have a look at this picture which runs the command and also an example from the comment based help 😀