Private/Save-File.ps1

function Save-File {
    <#
        .SYNOPSIS
            Downloads a file with Invoke-WebRequest and returns the downloaded file as a FileInfo object.
    #>

    [OutputType([System.IO.FileInfo])]
    [CmdletBinding(SupportsShouldProcess = $false)]
    param (
        [Parameter(Mandatory = $true, Position = 0)]
        [ValidateNotNullOrEmpty()]
        [System.String] $Uri
    )

    $downloadUri = $null
    if (-not [System.Uri]::TryCreate($Uri, [System.UriKind]::Absolute, [ref]$downloadUri) -or $downloadUri.Scheme -notin @("http", "https")) {
        throw [System.ArgumentException]::new("Uri must be an absolute HTTP or HTTPS URL.", "Uri")
    }

    $fileName = [System.IO.Path]::GetFileName($downloadUri.AbsolutePath)
    $fileName = [System.Uri]::UnescapeDataString($fileName)
    foreach ($invalidCharacter in [System.IO.Path]::GetInvalidFileNameChars()) {
        $fileName = $fileName.Replace([string]$invalidCharacter, "_")
    }
    if ([string]::IsNullOrWhiteSpace($fileName) -or $fileName -in @(".", "..")) {
        $fileName = "download"
    }

    $uniqueFileName = "$([guid]::NewGuid().ToString('N'))-$fileName"
    $OutFile = Join-Path -Path ([System.IO.Path]::GetTempPath()) -ChildPath $uniqueFileName
    Write-Verbose -Message "$($MyInvocation.MyCommand): Using save path: $OutFile."

    $originalSecurityProtocol = $null
    $restoreSecurityProtocol = $false
    try {
        $params = @{
            Uri             = $Uri
            OutFile         = $OutFile
            UseBasicParsing = $true
            UserAgent       = (Get-EvergreenUserAgent)
        }
        if (Test-PSCore) {
            $params.SslProtocol = "Tls12"
        }
        else {
            $originalSecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol
            [System.Net.ServicePointManager]::SecurityProtocol = $originalSecurityProtocol -bor [System.Net.SecurityProtocolType]::Tls12
            $restoreSecurityProtocol = $true
        }
        Invoke-WebRequest @params -ErrorAction Stop | Out-Null
    }
    catch {
        if (Test-Path -LiteralPath $OutFile) {
            try {
                Remove-Item -LiteralPath $OutFile -Force -ErrorAction Stop
            }
            catch {
                Write-Warning -Message "Failed to remove partial download '$OutFile': $($_.Exception.Message)"
            }
        }
        throw
    }
    finally {
        if ($restoreSecurityProtocol) {
            [System.Net.ServicePointManager]::SecurityProtocol = $originalSecurityProtocol
        }
    }

    Get-Item -LiteralPath $OutFile -ErrorAction Stop
}