Helper/Get-File.ps1

function Get-File {
    Param (
        [Parameter(Position=0, Mandatory=$true)] [string] $sourceUrl,
        [Parameter(Position=1, Mandatory=$true)] [string] $destinationFile,
                                                 [switch] $dontOverwrite,
                                                 [int]    $timeout = 5
    )

    # Check if existing
    if (Test-Path $destinationFile -PathType Leaf) {
        if ($dontOverwrite) { 
            return
        }
        Remove-Item -Path $destinationFile -Force
    }
    # Create destination directory
    $path = [System.IO.Path]::GetDirectoryName($destinationFile)
    if (!(Test-Path $path -PathType Container)) {
        New-Item -Path $path -ItemType Directory -Force | Out-Null
    }
    
    if (!$Silent) {
        Write-Verbose "Downloading $sourceUrl"
        Write-Verbose " to $destinationFile"
    }

    [Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12
    Add-Type -AssemblyName System.Net.Http
    $handler = New-Object System.Net.Http.HttpClientHandler
    $handler.UseDefaultCredentials = $true
    $httpClient = New-Object System.Net.Http.HttpClient -ArgumentList $handler
    $httpClient.Timeout = [Timespan]::FromSeconds($timeout)
    $stream = $null
    $fileStream = $null
    if ($dontOverwrite) {
        $fileMode = [System.IO.FileMode]::CreateNew
    }
    else {
        $fileMode = [System.IO.FileMode]::Create
    }
    try {
        $stream = $httpClient.GetStreamAsync($sourceUrl).GetAwaiter().GetResult()
        $fileStream = New-Object System.IO.Filestream($destinationFile, $fileMode)
        if (-not $stream.CopyToAsync($fileStream).Wait($timeout * 1000)) {
            throw "Timeout downloading file"
        }
    }
    finally {
        if ($fileStream) {
            $fileStream.Close()
            $fileStream.Dispose()
        }
        if ($stream) {
            $stream.Dispose()
        }
    }
}
Export-ModuleMember -Function Get-File