How to Download File from URL in PowerShell

Problem

This blog post will show you how to download a file from URL using PowerShell.

In this context, we will try to download latest Mozilla Firefox installer (executable file) from its direct download link: https://download.mozilla.org/?product=firefox-latest&os=win64&lang=en-US.

The download process consists of two parts:

  1. Define the download URL and the destination folder where the file will reside
  2. Download the file

All solutions below share all the steps above. They only differ in how they download the file.

Using Invoke-WebRequest

First, we need to define variables that hold the download URL and destination folder of the installer. Then, we use Invoke-WebRequest cmdlet to download the file and put it in destination folder.


# Define the download URL and the destination
$firefoxUrl = "https://download.mozilla.org/?product=firefox-latest&os=win64&lang=en-US"
$destination = "$env:TEMP\firefox_installer.exe"

# Download the Firefox installer
Invoke-WebRequest -Uri $firefoxUrl -OutFile $destination

Using Invoke-RestMethod

Similar to previous solution, but in this solution we use Invoke-RestMethod cmdlet to download the file. We can use this cmdlet because the communication is using HTTP(S) that is supported by RESTful services.


# Define the download URL and the destination
$firefoxUrl = "https://download.mozilla.org/?product=firefox-latest&os=win64&lang=en-US"
$destination = "$env:TEMP\firefox_installer.exe"

# Download the Firefox installer
Invoke-RestMethod -Uri $firefoxUrl -OutFile $destination

Using WebClient

Like previous solutions, but this one we will use WebClient class from .NET Framework to download the file since PowerShell is deeply integrated with .NET Framework.


# Define the download URL and the destination
$firefoxUrl = "https://download.mozilla.org/?product=firefox-latest&os=win64&lang=en-US"
$destination = "$env:TEMP\firefox_installer.exe"

# Download the Firefox installer
$WebClient = New-Object System.Net.WebClient
$webclient.DownloadFile($firefoxUrl, $destination)

Using HttpClient

We can also use HttpClient from .NET Framework to download the file.

There are two flavors in using .NET Framework, i.e., C# code from PowerShell. We can create the object using PowerShell syntax as in previous solution or we can also embed C# code in our script then invoke it.

In this case, we present both of the approaches.

Create C# object using PowerShell syntax

In this approach, we need to apply dispose pattern by enclosing each call to HttpClient constructor, GetStreamAsync and FileStream methods with try-finally block. It is optional to put catch block if we want to handle the exception specifically.

At finally block we close the connection after we have used disposable object, so that the file can be used or accessed by another process.

A more concise way to apply dispose pattern in C# is to use using statement, but since PowerShell doesn’t have the syntax we can use try-finally block.


using namespace System.IO
using namespace System.Net.Http

# Define the download URL and the destination
$firefoxUrl = "https://download.mozilla.org/?product=firefox-latest&os=win64&lang=en-US"
$destination = "$env:TEMP\firefox_installer.exe"

# Download the Firefox installer
try {
    $client = [HttpClient]::new()    
    try {
        $stream = $client.GetStreamAsync($firefoxUrl)
        try {
            $fileStream = [FileStream]::new($destination, [FileMode]::Create)
            $stream.GetAwaiter().GetResult().CopyTo($fileStream)       
        }
        finally {
            <#Do this after the try block regardless of whether an exception occurred or not#>
            $fileStream.Dispose()
        }         
    }
    finally {
        <#Do this after the try block regardless of whether an exception occurred or not#>
        $stream.Dispose()
    }    
}
finally {
    <#Do this after the try block regardless of whether an exception occurred or not#>
    $client.Dispose()
}

Embed C# code then invoke it from PowerShell

In this approach, we copy and paste our C# code to PowerShell, then enclose it with Add-Type -TypeDefinition in order to add it to PowerShell session. Then, we will be able to call the method to download the file from our script.


# Create C# Code to Download Firefox installer
Add-Type -TypeDefinition @"
    using System.IO;
    using System.Net.Http;

    public static class Downloader {
        public static void DownloadInstaller() {
            //Define the download URL and the destination
            string firefoxUrl = "https://download.mozilla.org/?product=firefox-latest&os=win64&lang=en-US";
            string destination = Path.Join(Path.GetTempPath(), "firefox_installer.exe");

            using (var client = new HttpClient())
            {
                using (var s = client.GetStreamAsync(firefoxUrl))
                {
                    using (var fs = new FileStream(destination, FileMode.OpenOrCreate))
                    {
                        s.Result.CopyTo(fs);
                    }
                }
            }
        }
    }
"@
[Downloader]::DownloadInstaller()

Conclusion

To download file from URL in PowerShell, there are some cmdlets we can use: using Invoke-WebRequest or Invoke-RestMethod.

We can also use .NET Framework class like WebClient or HttpClient to download the file.