PowerShell : apprenez à utiliser Invoke-WebRequest pour télécharger des fichiers
Sommaire
I. Présentation
Le langage PowerShell inclut les commandlets nécessaires pour télécharger des fichiers hébergés sur Internet ou sur votre serveur Web. PowerShell prend en charge plusieurs protocoles, notamment HTTP, HTTPS et FTP. Ainsi, nous pouvons télécharger des fichiers directement en ligne de commande ou dans un script. Il est également possible de spécifier des identifiants (credentials), pour s'authentifier auprès du serveur distant si ce dernier requiert une authentification.
Dans ce tutoriel, nous allons voir comment utiliser PowerShell pour effectuer le téléchargement d'un ou plusieurs ficheirs hébergés sur un serveur web (il pourrait s'agir, par exemple, d'un fichier GitHub). Finalement, ce tutoriel va répondre à la question suivante : Comment télécharger des fichiers sur internet avec PowerShell ?
- Envie d'apprendre PowerShell ? Découvrez notre cours gratuit : Débuter avec le langage PowerShell
Version originale de l'article : 20 février 2017
II. Téléchargement avec Invoke-WebRequest
Introduit à partir de PowerShell 3.0, le commandlet "Invoke-WebRequest" peut avoir plusieurs usages parce qu'il permet d'interagir directement avec un serveur Web, que ce soit pour effectuer des requêtes GET, POST, etc... Il permet notamment d'obtenir le code source d'une page et de pouvoir le parser ensuite.
Ce cmdlet permet aussi, et c'est ça qui nous intéresse aujourd'hui, de télécharger des fichiers hébergés sur un serveur web. Prenons l'exemple d'un exécutable hébergé sur GitHub, je pense que c'est un bon cas de figure, car GitHub héberge de nombreux fichiers. Concernant son fonctionnement, vous devez savoir qu'Invoke-WebRequest va d'abord mettre en mémoire tampon le fichier téléchargé, avant de l'écrire sur le disque une fois que le téléchargement sera complété.
Note : Le commandlet "Invoke-WebRequest" dispose d'un alias "wget" qui permet de raccourcir la commande et qui reprend la commande du même nom sous Linux.
Voici la syntaxe générique du commandlet Invoke-WebRequest dans le cadre d'un téléchargement :
Invoke-WebRequest -Uri "<lien-du-fichier-a-telecharger" -OutFile "<chemin-vers-fichier-destination>"
Ici, nous allons télécharger un package MSI correspondant à PowerShell, à partir du GitHub officiel du projet. Nous souhaitons stocker le fichier téléchargé dans le répertoire "C:\TEMP". Ce qui donne la commande suivante :
Invoke-WebRequest -Uri "https://github.com/PowerShell/PowerShell/releases/download/v7.4.6/PowerShell-7.4.6-win-x64.msi" -OutFile "C:\temp\PowerShell-7.4.6-win-x64.msi"
Une barre de progression indique le nombre d'octets téléchargés en temps réel, ce qui permet de suivre l'avancement du téléchargement. Une fois l'opération terminée, le fichier téléchargé sera accessible à l'emplacement de destination. Attention, si le fichier de destination existe déjà, il sera écrasé et PowerShell ne vous avertira pas.
Note : Il est indispensable de préciser le nom du fichier de sortie en tant que valeur du paramètre "-OutFile", car il n'est pas implicite. Vous pouvez remettre le même nom que celui d'origine ou un nom différent.
III. S'authentifier et télécharger un fichier avec PowerShell
Le téléchargement de certains fichiers est protégé et nécessitent une authentification préalable, notamment via la méthode d'authentification HTTP. Le cmdlet Invoke-WebRequest dispose d'un paramètre "-Credential" que vous pouvez utiliser pour indiquer des identifiants (via un objet PSCredentials).
Ce qui pourrait donner les deux lignes suivantes :
$Identifiants = Get-Credential
Invoke-WebRequest -Uri "https://serveur.it-connect.local/protected/mon-fichier.zip" -OutFile "C:\temp\mon-fichier.zip" -Credential $Identifiants
Dans ce cas, vous devez saisir les identifiants de façon interactive, et donc manuellement. Si ce script doit être exécuté de manière automatique, avec une tâche planifiée par exemple, vous devez stocker le mot de passe dans le script. Afin d'éviter de le stocker en clair, vous pouvez lire cet article qui expose une méthode que vous pouvez appliquer :
Remarque : la commande Invoke-WebRequest a d'autres paramètres, comme "-UserAgent" pour préciser une chaine personnalisée pour le User-Agent, ainsi que "-Method" pour spécifier la méthode HTTP à utiliser (GET, POST, etc.).
IV. Comment télécharger plusieurs fichiers avec PowerShell ?
Nous venons de voir comment télécharger un fichier avec Invoke-WebRequest. Mais, comment faire s'il y a plusieurs fichiers à télécharger ? Il y a plusieurs façons d'aborder cette problématique. Il est envisageable de créer un fichier CSV avec deux colonnes : URL vers le fichier source et Nom du fichier de destination. Une autre approche consiste à récupérer le nom du fichier à partir de l'URL et à le réutiliser pour le nom du fichier de sortie. C'est ce que nous allons tenter de faire !
Pour tenter de récupérer le nom du fichier, nous pouvons découper l'URL en plusieurs parties grâce au caractère slash "/". En principe, ce qui se situe après le dernier slash correspond au nom de notre fichier ! Pour cela, nous allons utiliser la méthode Split() puis récupérer la dernière valeur du résultat grâce à l'index "-1". Ce qui donne :
# URL à analyser
$URL = "https://github.com/PowerShell/PowerShell/releases/download/v7.4.6/PowerShell-7.4.6-win-x64.msi"
# Récupération du nom de fichiers
$NomFichier = $URL.Split("/")[-1]
# Valeur obtenue
PowerShell-7.4.6-win-x64.msi
Ci-dessous, le code complet pour télécharger tous les fichiers ajoutés à une liste représentée par le tableau $ListeDesFichiers :
# Liste des URLs des fichiers à télécharger
$ListeDesFichiers = @(
"https://github.com/PowerShell/PowerShell/releases/download/v7.4.6/PowerShell-7.4.6-win-x64.msi",
"https://github.com/microsoft/PowerToys/releases/download/v0.87.1/PowerToysSetup-0.87.1-x64.exe",
"https://download.microsoft.com/download/9/5/b/95be347e-c49e-4ede-a205-467c85eb1674/Administrative%20Templates%20(.admx)%20for%20Windows%2011%20Sep%202024%20Update.msi"
)
# Répertoire de destination pour les fichiers téléchargés
$DossierDestination = "C:\TEMP"
# Télécharger chaque fichier
foreach ($URL in $ListeDesFichiers) {
try {
# Extraire le nom du fichier depuis l'URL
$NomFichier = $URL.Split("/")[-1]
# Construire le chemin complet pour le fichier téléchargé
$FichierDestination = "$DossierDestination\$NomFichier"
# Télécharger le fichier
Invoke-WebRequest -Uri $URL -OutFile $FichierDestination
Write-Host "Téléchargement réussi : $NomFichier" -ForegroundColor Green
} catch {
Write-Host "Erreur lors du téléchargement de $URL : $_" -ForegroundColor Red
}
}
S'il y a une erreur lors du téléchargement d'un fichier, celle-ci sera visible dans la console, car nous effectuons un retour pour chaque fichier téléchargé. Voici un exemple de sortie :
V. Télécharger un fichier avec PowerShell 2.0
Pour finir, nous allons évoquer une méthode compatible PowerShell 2.0, pour ceux qui doivent télécharger un fichier sur une machine où une ancienne version de PowerShell est encore utilisée (ou si vous souhaitez écrire des scripts rétrocompatibles).
Avec l'ancienne méthode c'est-à-dire quand Invoke-WebRequest n'existait pas, il fallait passer par la création d'un objet et ensuite invoquer une méthode pour télécharger un objet. Concrètement, nous allons créer un objet de type "System.Net.WebClient" et le stocker dans une variable "$WebRequest". Ensuite, nous allons exécuter la méthode "DownloadFile" sur cet objet. Cette méthode requiert deux paramètres : le lien vers le fichier et le chemin de destination, ce qui doit vous rappeler la syntaxe d'un certain Invoke-WebRequest...
$WebRequest = New-Object System.Net.WebClient $WebRequest.DownloadFile("<lien-vers-le-fichier>","<chemin-vers-la-destination>")
Si nous reprenons le même exemple que précédemment, voici la syntaxe :
$WebRequest = New-Object System.Net.WebClient
$WebRequest.DownloadFile("https://github.com/PowerShell/PowerShell/releases/download/v7.4.6/PowerShell-7.4.6-win-x64.msi","C:\temp\PowerShell-7.4.6-win-x64.msi")
Lors du téléchargement d'un fichier avec cette méthode, il n'y a pas d'informations sur la progression, mais le fichier sera bel et bien téléchargé.
Note : Vous pouvez utiliser la méthode "DownloadFileAsync" au lieu de "DownloadFile" pour réaliser un téléchargement en arrière-plan, c'est-à-dire que le script n'attend pas la fin du téléchargement pour continuer.
Si vous obtenez une erreur comme "Impossible de créer le type. Seuls les types principaux sont pris en charge dans ce mode de langage." sur votre machine, c'est que votre PowerShell est "bridé" par une stratégie au niveau du système. Il est surement en mode "ConstrainedLanguage", au lieu de "FullLanguage" qui est le mode par défaut, ce qui bloque l'accès à certains objets et classes (voir cette page).
VI. Conclusion
Le téléchargement de fichiers en PowerShell est une opération simple que vous pouvez accomplir à l'aide du cmdlet Invoke-WebRequest. Néanmoins, cette méthode peut ne pas convenir si vous avez une contrainte liée à la performance. Dans ce cas, je vous recommande de regarder du côté des transferts BITS, via le module BitsTransfer de PowerShell.
Voici des ressources additionnelles pour vous accompagner :
- Le transfert de fichiers intelligent dit "BITS" via le module "BitsTransfer"
- Microsoft Learn - Invoke-WebRequest
- Copier des fichiers avec PowerShell et la commande "Copy-Item"
j’ai fait un petit billet a ce sujet si besoin sur mon blog ici :
http://etienne.deneuve.xyz/2015/12/16/get-nexttrain/
pour ceux qui cherchent des exemples avec des API par exemple 😉
Bonjour Florian,
Merci beaucoup pour ce script qui est très utile.
Je me permets de vous poser une question pour connaitre la version de cet exécutable sans avoir à le télécharger.
Je vous remercie par avance pour votre travail et votre réponse.
Bien cordialement
Gérard
Bonjour et merci pour le partage de connaissance.
Est-ce qu’il y a une limite en terme de poids du fichier ?
J’ai des archives qui pèsent un peu moins de 2,5Go et le téléchargement ne se termine avec un message d’erreur.
Par contre si je DL une image (2Mo) là ça passe sans problème.
Je fais ça sur un serveur Windows 2008 R2 et avec PS 2.0
Bonjour,
Il y a peut être une limitation mais je ne la connais pas, ça pourrait être lié à la version 2.0 de PS. Avez-vous essayé sur un host avec une version plus récente ? Sinon il faudrait essayer avec BITS.
Cordialement,
Florian
Bonjour,
Est-il possible de télécharger un fichier a partir d’une autre adresse IP
Exemple :
J’ai la 192.168.1.2 et la 85.52.61.2
Je veux passer par la 85.52.61.2 pour lancer mon téléchargement
Merci par avance.