public/Get-NewPackageFile.ps1

function Get-NewPackageFile {
    <#
    .SYNOPSIS
    Cmdlet that saves a file from a file path, UNC, or URI and saves it to the specified location.
    .DESCRIPTION
    Get-NewPackageFile is a function that when provided with a Source file path, UNC, or URI (as a string) and a Destination path or
    UNC (as a string) will copy or download the Source file to the Destination. Characters of a space (" ") or an escaped space ("%20")
    are replaced with an underscore ("_") when saved to the Destination. Returns object information of the saved file.
    .PARAMETER Source
    A string that must be a file path, UNC, or URI of the file to be saved to the Destination location. Wildcards are not permitted.
    .PARAMETER Destination
    A string that must be a file path or UNC where the Source file will be saved. Wildcards are not permitted.
    .EXAMPLE
    Get-NewPackageFile -Source "C:\Test\File1.txt" -Destination "D:\Temp\File2.txt"
    .EXAMPLE
    Get-NewPackageFile -Source "C:\Test\File1.txt" -Destination "D:\Temp\"
    .EXAMPLE
    Get-NewPackageFile -Source "C:\Test\File1.txt" -Destination "\\fileserver\Temp\File1.txt"
    .EXAMPLE
    Get-NewPackageFile -Source "\\fileserver\Test\File1.txt" -Destination "D:\Temp\File1.txt"
    .EXAMPLE
    Get-NewPackageFile -Source "\\fileserver1\Test\File1.txt" -Destination "\\fileserver2\Temp\File1.txt"
    .EXAMPLE
    Get-NewPackageFile -Source "https://webserver.xyz/Test/File1.txt" -Destination "C:\Temp\File1.txt"
    .EXAMPLE
    Get-NewPackageFile -Source "https://webserver.xyz/Test/File1.txt" -Destination "\\fileserver\Temp\File1.txt"
    .INPUTS
    String
    .OUTPUTS
    System.IO.FileInfo
    Get-NewPackageFile returns information on the file saved in the location specified in the Destination parameter.
    .NOTES
    If the Destination parameter is only a file path and does not include a filename, the filename obtained from the Source parameter
    is used during the copy. Requires use of the "Get-RedirectedUri" function.
#>

    
    [CmdletBinding(SupportsShouldProcess)]
    param (
        [Parameter(Mandatory = $true,
            HelpMessage = "Enter a valid Source file path, UNC, or URI.")]
        [ValidateNotNullOrEmpty()]
        [string]$Source,

        [Parameter(Mandatory = $true,
            HelpMessage = "Enter a valid Destination file path or UNC.")]
        [ValidateNotNullOrEmpty()]
        [string]$Destination
    )

    process {
        try {
            # Work with Source input
            $SourceScheme = ([System.Uri]$Source).Scheme
            if ($SourceScheme -match "file") {
                # Do File stuff
                Write-Verbose -Message "Source scheme is file"
                # If file does not exist, error
                if (Test-Path -LiteralPath $Source -PathType Leaf) {
                    # Put the full Source and filename into variables for use later
                    $FullSource = $Source
                    $SourceFile = Split-Path -Path $Source -Leaf

                }
                else {
                    throw "Source is a directory or file does not exist: $Source"
                }
            }
            elseif ($SourceScheme -match "http") {
                # Do HTTP(S) stuff
                Write-Verbose -Message "Source scheme is http(s)"
                # Get the redirected URL of the Source so the file can be downloaded
                $FullSource = Get-RedirectedURI -URI $Source
                # Get the unescaped Source filename from the URL
                $URIFile = Split-Path $FullSource -Leaf
                $UnescapedFile = [System.Uri]::UnescapeDataString($URIFile)
                # Replace any space charaters with underscores
                $SourceFile = $UnescapedFile.Replace("%20", "_").Replace(" ", "_")
            }
            else {
                throw "Invalid Source path type: $SourceScheme. Must be type: file, http, or https."
            }
            Write-Verbose -Message "Source filename: $SourceFile"

            # Work with Destination input
            $DestinationScheme = ([System.Uri]$Destination).Scheme
            if ($DestinationScheme -match "file") {
                # Do Destination stuff
                Write-Verbose -Message "Destination scheme is file"
                if ($null -eq [IO.Path]::GetExtension($Destination) -or "" -eq [IO.Path]::GetExtension($Destination)) {
                    # Filename not present in Destination, use filename from Source
                    $DestinationPath = $Destination
                    if ($DestinationPath.Substring($DestinationPath.Length - 1) -eq "\") {
                        # Last character of Source input is a backslash, no need to add it to the full destination
                        $FullDestination = "$Destination" + "$SourceFile"
                    }
                    else {
                        # Last character of Source input is not a backslash, add one to the full destination
                        $FullDestination = "$Destination" + "\" + "$SourceFile"
                    }
                }
                else {
                    # Filename present in Destination
                    # Put the Destination path into svariable for possible use later
                    $DestinationPath = Split-Path -Path $Destination
                    $FullDestination = $Destination
                }
            }
            else {
                throw "Invalid Destination path type: $DestinationScheme; must be type: file."
            }

            # If Destination path doesn't exist, create it
            if (-not(Test-Path -LiteralPath $DestinationPath -PathType Container)) {
                if ($PSCmdlet.ShouldProcess($DestinationPath, "Create directory")) {
                    Write-Verbose -Message "Creating Destination directory: $DestinationPath"
                    [void](New-Item -Path $DestinationPath -ItemType Directory -Force)
                }
            }

            # Copy or download file to destination
            Write-Verbose -Message "Saving $FullSource to $FullDestination"
            if ($SourceScheme -match "file") {
                # Copy file from Source to Destination
                if ($PSCmdlet.ShouldProcess(“$FullSource to $FullDestination”, "File copy")) {
                    Copy-Item -Path $FullSource -Destination $FullDestination -Force
                }
            }
            if ($SourceScheme -match "http") {
                # Download file from Source to Destination
                if ($PSCmdlet.ShouldProcess(“$FullSource to $FullDestination”, "Download file")) {
                    Invoke-WebRequest -Uri $FullSource -OutFile $FullDestination
                }
            }

            # Return object information on saved file
            if ($PSCmdlet.ShouldProcess($FullDestination, "Return file information")) {
                Get-ChildItem -Path $FullDestination
            }

        }
        catch {
            throw $_
        }
    }

}