PowerShell Script to Download Files from URLs: Automate and Verify File Integrity

by Team Ninja
  |  
reviewed by Stan Hunter
How to Download Files From URLs with PowerShell

In the fast-paced world of IT and managed services, efficiency and automation are key. A particularly useful tool that every IT professional or MSP should have in their toolkit is a PowerShell script capable of downloading files directly from a URL. In this blog post, we delve deeper into the workings of such a script, discuss real-world usage scenarios, and expound on the benefits of using PowerShell to download files from URLs. 

The Script: PowerShell Download File From URL

#Requires -Version 2.0

<#
.SYNOPSIS
    Downloads a file from a provided URL to a path.
.DESCRIPTION
    Downloads a file from a provided URL to a path. Can compare the hash and automatically remove the failed download.
    UserName and Password can be used for URL's that require it, basic authentication is expected.
.EXAMPLE
    -Url "https://www.google.com/" -FilePath "C:\temp\index.html"
    Downloads the index html page from google.com to C:\temp\index.html
.EXAMPLE
    -Url "https://www.nirsoft.net/utils/advancedrun.zip" -FilePath "C:\temp\advancedrun.zip" -Hash "b2c65aa6e71b0f154c5f3a8b884582779d716ff2c03d6cdca9e157f0fe397c9c" -Algorithm SHA256
    Downloads the advancedrun.zip file from nirsoft to C:\temp\advancedrun.zip and validates that the SHA256 hash matches
.EXAMPLE
    -Url "https://www.nirsoft.net/utils/advancedrun.zip" -FilePath "C:\temp\advancedrun.zip" -Hash "b2c65aa6e71b0f154c5f3a8b884582779d716ff2c03d6cdca9e157f0fe397c9c" -AutoRemove
    Downloads the advancedrun.zip file from nirsoft to C:\temp\advancedrun.zip and validates that the SHA256 hash matches. If the hash does not match the file will be removed.
    Not specifying Algorithm defaults to SHA256.
.OUTPUTS
    String[]
.NOTES
    Minimum OS Architecture Supported: Windows 7, Windows Server 2008 R2
    Release Notes:
    Initial Release
    (c) 2023 NinjaOne
    By using this script, you indicate your acceptance of the following legal terms as well as our Terms of Use at https://www.ninjaone.com/terms-of-use.
    Ownership Rights: NinjaOne owns and will continue to own all right, title, and interest in and to the script (including the copyright). NinjaOne is giving you a limited license to use the script in accordance with these legal terms. 
    Use Limitation: You may only use the script for your legitimate personal or internal business purposes, and you may not share the script with another party. 
    Republication Prohibition: Under no circumstances are you permitted to re-publish the script in any script library or website belonging to or under the control of any other software provider. 
    Warranty Disclaimer: The script is provided “as is” and “as available”, without warranty of any kind. NinjaOne makes no promise or guarantee that the script will be free from defects or that it will meet your specific needs or expectations. 
    Assumption of Risk: Your use of the script is at your own risk. You acknowledge that there are certain inherent risks in using the script, and you understand and assume each of those risks. 
    Waiver and Release: You will not hold NinjaOne responsible for any adverse or unintended consequences resulting from your use of the script, and you waive any legal or equitable rights or remedies you may have against NinjaOne relating to your use of the script. 
    EULA: If you are a NinjaOne customer, your use of the script is subject to the End User License Agreement applicable to you (EULA).
.COMPONENT
    Download
#>

[CmdletBinding()]
param (
    # Url that will be used to download a file
    [Parameter(Mandatory = $true)]
    [string]$Url,
    # File path that the file will be placed
    [Parameter(Mandatory = $true)]
    [string]$FilePath,
    # Expected hash of downloaded file
    [Parameter()]
    [string]$Hash,
    # Hashing Algorithm to use for hash comparison
    [Parameter()][ValidateSet("SHA1", "SHA256", "SHA384", "SHA512", "MD5")]
    [string]$Algorithm = "SHA256",
    # Removes failed download automatically
    [Parameter()]
    [switch]$AutoRemove,
    # UserName
    [Parameter()]
    [string]$UserName,
    # Password
    [Parameter()]
    [string]$Password
)

# For PowerShell 2.0 and 3.0 compatibility
if ($PSVersionTable.PSVersion.Major -lt 4) {
    function Get-FileHash {
        param (
            [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
            [string[]]
            $Path,
            [Parameter(Mandatory = $false)]
            [ValidateSet("SHA1", "SHA256", "SHA384", "SHA512", "MD5")]
            [string]
            $Algorithm = "SHA256"
        )
        $Path | ForEach-Object {
            # Only hash files that exist
            $CurrentPath = $_
            if ($(Test-Path -Path $CurrentPath -ErrorAction SilentlyContinue)) {
                
                $HashAlgorithm = New-Object -TypeName System.Security.Cryptography.$($Algorithm)CryptoServiceProvider
                $Hash = [System.BitConverter]::ToString($hashAlgorithm.ComputeHash([System.IO.File]::ReadAllBytes($CurrentPath)))
                @{
                    Algorithm = $Algorithm
                    Path      = $Path
                    Hash      = $Hash.Replace('-', '')
                }
            }
        }
    }
}

# For PowerShell 2.0 compatibility
if ($PSVersionTable.PSVersion.Major -le 2) {
    $client = New-Object System.Net.WebClient
    if ($PSBoundParameters.ContainsKey("UserName") -and $PSBoundParameters.ContainsKey("Password")) {
        $client.Credentials = New-Object System.Net.NetworkCredential($UserName, $(ConvertTo-SecureString -String $Password -AsPlainText -Force))
    }
    elseif (
        ($PSBoundParameters.ContainsKey("UserName") -and -not $PSBoundParameters.ContainsKey("Password")) -or
        (-not $PSBoundParameters.ContainsKey("UserName") -and $PSBoundParameters.ContainsKey("Password"))
    ) {
        Write-Error "UserName and Password parameters have to be used together."
        exit 1
    }
    try {
        if ($null -ne $FilePath) {
            $client.DownloadFile($Url, $FilePath)
        }
        else {
            # Similar functionality to Invoke-WebRequest if -OutFile was not used, null, or an empty string
            # Defaults to the current directory
            $client.DownloadFile($Url, ".\")
        }
        
    }
    catch {
        Write-Error $_
        Write-Host "System.Net.WebClient Failed to download from $Url to $FilePath"
        exit 1
    }
}
else {
    $Splat = @{
        Uri        = $Url
        OutFile    = $FilePath
        Credential = if ($PSBoundParameters.ContainsKey("UserName") -and $PSBoundParameters.ContainsKey("Password")) {
            New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $UserName, $SecureString
        }
        else { $null }
    }
    try {
        Invoke-WebRequest @Splat
    }
    catch {
        Write-Error $_
        Write-Host "Invoke-WebRequest failed to download from $Url to $FilePath"
        exit 1
    }
    
}
Write-Host "Computing hash using $Algorithm"
$ComputedHash = $(Get-FileHash -Path $FilePath -Algorithm $Algorithm).Hash
Write-Host "Computed hash for $FilePath is $ComputedHash"
if ($PSBoundParameters.ContainsKey("Hash")) {
    if ($ComputedHash -like $Hash) {
        Write-Host "$FilePath hash matched!"
    }
    else {
        Write-Error "$FilePath hash did not match!"
        Write-Host "Computed hash of $FilePath was:"
        Write-Host "$ComputedHash"
        Write-Host "Expected hash was:"
        Write-Host "$Hash"
        if ($AutoRemove) {
            Write-Host "Removing failed download."
            try {
                # This should always remove the file
                Remove-Item $Path -Force -Confirm:$false -ErrorAction SilentlyContinue
                Write-Host "Removed failed download."
            }
            catch {
                if ($(Test-Path -Path $Path -ErrorAction SilentlyContinue)) {
                    Write-Host "Failed to remove failed download."
                }
                else {
                    Write-Host "Removed failed download."
                }
            }
        }
        exit 1
    }
}

Access over 700+ scripts in the NinjaOne Dojo

Get Access

Real-World Scenarios: Putting the Script to Use

This script has a wide variety of applications.

Regularly Downloading Updates

If you're managing a network where software updates are released as downloadable files on a vendor's website, you can automate the download process with this script.

Data Collection

If you're gathering data from the web for analysis and the data is provided as downloadable files, this script can automate the process and ensure the downloaded data is intact.

Automating Backup of Online Assets

If your organization stores important files or assets online, you can use this script to automate regular downloads for backup purposes.

Why Use PowerShell to Download Files from URLs?

Automation

Automation is a key benefit of this PowerShell script. By automating the process of downloading files from a URL, you can save time, reduce the chance of human error, and focus on more complex tasks that can't be automated. 

Efficiency

Using PowerShell to download files from URLs can also boost efficiency. You can manage large numbers of downloads without having to manually navigate to each URL and initiate the download process. 

File Integrity Verification

The script's hash comparison feature ensures the integrity of downloaded files. By comparing the computed hash of the downloaded file to the expected hash, it helps verify that the file has been downloaded correctly and is not corrupted, providing peace of mind when deploying patches or updates across a network. 

Final Thoughts

As we've seen, PowerShell scripts can greatly streamline your IT operations, and this is where NinjaOne can be particularly valuable. With its comprehensive IT monitoring and management suite, it supports the use of scripts like the one discussed here to automate routine tasks and manage your IT infrastructure more efficiently. The ability to download files directly from URLs and validate their integrity is just one example of what you can achieve with NinjaOne. By integrating these scripts into NinjaOne's robust platform, you can further enhance your IT operations, enabling a more proactive and efficient approach to managing your IT environment.  

Access this script and hundreds more within NinjaOne. 

Next Steps

Building an efficient and effective IT team requires a centralized solution that acts as your core service deliver tool. NinjaOne enables IT teams to monitor, manage, secure, and support all their devices, wherever they are, without the need for complex on-premises infrastructure.

Learn more about Ninja Endpoint Management, check out a live tour, or start your free trial of the NinjaOne platform.

NinjaOne Rated #1 in RMM, Endpoint Management and Patch Management

Monitor, manage, and secure any device, anywhere

NinjaOne gives you complete visibility and control over all your devices for more efficient management.

Too many tools in too many places?

See how tool sprawl impacts IT and what you can do to solve it.