Comment télécharger des fichiers web avec PowerShell ?
Sommaire
I. Présentation
Le langage PowerShell inclut les commandlets nécessaires au téléchargement de fichiers hébergés sur Internet, que ce soit sur un hébergement HTTP, HTTPS ou FTP, on pourra télécharger des fichiers directement en ligne de commande. Il est également possible de spécifier des credentials, si le serveur qui héberge le fichier requiert une authentification.
Dans ce tutoriel, on ne parlera pas du téléchargement de fichiers à partir d'un partage SMB (ou autre), mais uniquement pour des fichiers hébergés sur un serveur web (qui peut être sur internet, par exemple un fichier GitHub). Finalement, ce tutoriel permet de répondre à la question suivante : Comment télécharger des fichiers sur internet avec PowerShell ?
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.
Il 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.
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>"
Le lien direct vers le fichier EXE que je veux télécharger est : "https://github.com/tabad/fusioninventory-agent-windows-installer/releases/download/2.3.18/fusioninventory-agent_windows-x64_2.3.18.exe"
Je souhaite télécharger le fichier dans le répertoire "C:\temp". Ce qui donne la commande suivante :
Invoke-WebRequest -Uri "https://github.com/tabad/fusioninventory-agent-windows-installer/releases/download/2.3.18/fusioninventory-agent_windows-x64_2.3.18.exe" -OutFile "C:\temp\fusioninventory-agent_windows-x64_2.3.18.exe"
Note : Il est indispensable de préciser le nom du fichier de sortie .exe dans le 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.
Une barre de progression indique le nombre d'octets téléchargés en temps réel :
Avec la commande "Get-ChildItem" suivit du chemin, on pourra vérifier l'existence du fichier :
Si je reviens sur le fonctionnement du commandlet "Invoke-WebRequest", par défaut c'est-à-dire si l'on ne met pas le paramètre "OutFile" le résultat (donc le fichier) est envoyé dans le pipeline, ce qui n'est pas ce que l'on veut quand on veut télécharger seulement un fichier. Par contre, si vous souhaitez conserver la sortie dans le pipeline tout en téléchargeant le fichier, il faudra ajouter le paramètre "-PassThru" qui permet de forcer la sortie en pipeline en plus de "-OutFile".
Pour aller plus loin : Aide Invoke-WebRequest
III. Télécharger un fichier avec PowerShell 2.0
Maintenant, nous allons poursuivre ce tutoriel avec une méthode compatible PowerShell 2.0, pour ceux qui utilisent encore cette version ou qui souhaitent é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.
On va créer un objet de type "System.Net.WebClient" et le stocker dans une variable "$WebRequest". Ensuite, on va 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'Invoke-WebRequest.
$WebRequest = New-Object System.Net.WebClient $WebRequest.DownloadFile("<lien-vers-le-fichier>","<chemin-vers-la-destination>")
Si je reprends le même exemple que précédemment, voici la syntaxe :
$WebRequest = New-Object System.Net.WebClient $WebRequest.DownloadFile("https://github.com/tabad/fusioninventory-agent-windows-installer/releases/download/2.3.18/fusioninventory-agent_windows-x64_2.3.18.exe","C:\temp\fusioninventory-agent_windows-x64_2.3.18.exe")
Voici un aperçu :
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.
Pour aller plus loin : Aide Net.WebClient
Si vous cherchiez une solution pour télécharger un fichier via SMB, je vous oriente vers deux pistes :
- Le commandlet "Copy-Item"
- Le transfert de fichiers intelligent dit "BITS" via le module "BitsTransfer"
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.