PowerShell Wget: Descargar archivos fácilmente

¿Necesitas descargar archivos de la web pero odias hacer clic repetidamente en enlaces? Si tu trabajo implica descargar archivos de la web regularmente, probablemente querrás automatizar la tarea. ¿Por qué no usar PowerShell para descargar archivos de manera similar a wget en PowerShell?

Windows PowerShell y PowerShell vienen con capacidades de descarga de archivos. Usar PowerShell para descargar archivos es cuestión de saber qué cmdlets y clases .NET utilizar y cómo utilizarlos.

En este artículo, aprenderás las diversas formas de utilizar PowerShell para descargar archivos de la web.

Prerrequisitos

Dado que este es un artículo de aprendizaje práctico, hay algunos requisitos previos para asegurarse de que puedas seguir los ejemplos. A continuación se presentan los requisitos básicos.

  • A computer that is running on Windows 10 or higher. This computer is where you will run the scripts/commands featured in this article.
  • Windows PowerShell 5.1 o PowerShell 7.1 (recomendado).
    • Windows 10 ya incluye Windows PowerShell 5.1.
  • A web site that hosts the files to download.
    • Para descargas de archivos no autenticadas, considera usar el sitio Tele2 Speedtest, que es gratuito.
    • Si deseas probar descargas de archivos con autorización, es posible que debas construir tu propio servidor de archivos HTTP. Un ejemplo de un servidor de archivos HTTP gratuito es HFS de Rejetto.

Usar PowerShell para descargar archivos desde URLs: Cuatro formas

Existen cuatro métodos para utilizar PowerShell para descargar archivos que no dependen de herramientas de terceros. Estos son:

  • Invoke-WebRequest
  • Invoke-RestMethod
  • Start-BitsTransfer
  • .NET WebClient Class.

Cualquiera de estos cuatro métodos que utilices, la lógica y los componentes para hacer que funcionen son los mismos. Debe haber una URL de origen que apunte a la ubicación del archivo y la ruta de destino para guardar los archivos descargados. Si es necesario por el servidor web, también debes ingresar las credenciales.

Las siguientes secciones muestran cada uno de estos cuatro métodos. Al final, depende de ti decidir qué camino adaptarías al usar PowerShell para descargar archivos.

Usar Invoke-WebRequest como alternativa a PowerShell wget

El primer método en PowerShell para descargar archivos es utilizando el cmdlet Invoke-WebRequest. Quizás el cmdlet más utilizado en este artículo, Invoke-WebRequest, puede descargar enlaces HTTP, HTTPS y FTP.

Ya sea que la ubicación de origen requiera que los usuarios inicien sesión, el cmdlet Invoke-WebRequest puede manejar solicitudes con credenciales también.

Para descargar un archivo, la sintaxis a continuación muestra los parámetros mínimos requeridos para lograr el resultado deseado.

Invoke-WebRequest -Uri <source> -OutFile <destination>

Por ejemplo, el código a continuación descarga un archivo con el nombre 10MB.zip desde un sitio web. Luego guarda el archivo descargado en C:\dload\10MB.zip. Puedes copiar el código a continuación y pegarlo en tu sesión de PowerShell para probar.

# Ubicación del archivo fuente
$source = 'http://speedtest.tele2.net/10MB.zip'
# Destino para guardar el archivo
$destination = 'c:\dload\10MB.zip'
# Descargar el archivo
Invoke-WebRequest -Uri $source -OutFile $destination

La demostración a continuación muestra el resultado esperado después de ejecutar el código anterior en PowerShell. Como puedes ver, la descarga del archivo fue exitosa.

PowerShell wget : Downloading a file using Invoke-WebRequest

¿Y si se requiere autenticación para acceder? Por ejemplo, el código a continuación descarga un archivo de un sitio web privado donde los usuarios deben iniciar sesión.

$source = 'https://mirror.lzex.ml/100MB.zip'
$destination = 'c:\dload\100MB.zip'
Invoke-WebRequest -Uri $source -OutFile $destination

Sin embargo, la descarga falló debido a un acceso no autorizado.

Downloading failed due to unauthorized access

Si se requiere autenticación, debes agregar credenciales a la solicitud utilizando el parámetro -Credential. La primera línea en el código a continuación te solicita ingresar las credenciales (nombre de usuario y contraseña) y las almacena en la variable $credential.

$credential = Get-Credential
$source = 'https://mirror.lzex.ml/100MB.zip'
$destination = 'c:\dload\100MB.zip'
Invoke-WebRequest -Uri $source -OutFile $destination -Credential $credential

La demostración a continuación muestra lo que esperarías ver al ejecutar el código anterior en PowerShell. Como puedes ver, el cmdlet Get-Credential solicitó una solicitud de credenciales de PowerShell. Esta vez, el uso de las credenciales con Invoke-WebRequest resultó en una descarga exitosa.

Downloading a file with authentication

Relacionado: Usando el cmdlet Get-Credential de PowerShell y todo sobre credenciales

Buscar Errores de Análisis al Usar Invoke-WebRequest

A crucial thing to remember when using Invoke-WebRequest in Windows PowerShell is that, by default, this cmdlet uses the Internet Explorer engine to parse data. The error below may happen when using Invoke-WebRequest on computers without the Internet Explorer in it.

Tendrás que volver a emitir tu comando, pero esta vez, incluye el interruptor -UseBasicParsing.

Invoke-WebRequest -Uri <source> -OutFile <destination> -UseBasicParsing

En Windows PowerShell, es posible que reciba un mensaje de error: El contenido de respuesta no se puede analizar porque el motor de Internet Explorer no está disponible, o la configuración de inicio de Internet Explorer no está completa. Especifique el parámetro UseBasicParsing e intente nuevamente.

A partir de PowerShell Core 6.0, el cmdlet Invoke-WebRequest usa solo análisis básico. Por lo tanto, el parámetro -UseBasicParsing ya no es necesario.

Usando Invoke-RestMethod

El cmdlet Invoke-RestMethod se trata más de enviar una solicitud HTTP o HTTPS a un servicio web RESTful. Este cmdlet es más adecuado para solicitudes que interactúan con APIs REST como el Graph API de Microsoft.

Cuando se trata de descargar archivos directamente desde la web, Invoke-RestMethod es una excelente opción. No se deje engañar pensando lo contrario. No hay mucha diferencia entre usar Invoke-RestMethod e Invoke-WebRequest cuando se usan para descargar archivos desde un enlace web directo.

Descargar un archivo usando Invoke-RestMethod

Para descargar un archivo usando Invoke-RestMethod, use la siguiente sintaxis. Notará que el comando utiliza los mismos parámetros que Invoke-WebRequest.

Invoke-RestMethod -Uri <source> -OutFile <destination>

En el código de ejemplo a continuación, el archivo se descarga desde la URL especificada en la variable $source. Luego, se guarda en la ruta definida en la variable $destination.

$source = 'http://speedtest.tele2.net/10MB.zip'
$destination = 'c:\dload\10MB.zip'
Invoke-RestMethod -Uri $source -OutFile $destination

Si la fuente requiere autenticación, puedes pasar las credenciales usando el parámetro -Credential. El ejemplo a continuación solicita las credenciales y las almacena en la variable $credential. El valor de la variable $credential luego se pasa al parámetro -Credential.

También, dado que el enlace del archivo es una fuente HTTP y no HTTPS, significa que estás enviando una autenticación no cifrada. Típicamente, deberías evitar usar fuentes HTTP por motivos de seguridad. Pero si necesitas usar una fuente HTTP, necesitas agregar el interruptor -AllowUnencryptedAuthentication a tu comando.

$credential = Get-Credential
$source = 'http://speedtest.tele2.net/10MB.zip'
$destination = 'c:\dload\10MB.zip'
Invoke-RestMethod -Uri $source -OutFile $destination -Credential $credential -AllowUnencryptedAuthentication

Usando Start-BitsTransfer

Start-BitsTransfer está diseñado específicamente para transferir archivos entre computadoras cliente y servidor. Este cmdlet de PowerShell depende del Servicio de Transferencia Inteligente en Segundo Plano (BITS) que es nativo del sistema operativo Windows.

Debido a que Start-BitsTransfer requiere BITS para funcionar, significa que este cmdlet no está disponible en computadoras que no sean Windows. Por otro lado, Start-BitsTransfer disfruta de los beneficios de BITS en sí mismo. Algunos de estos beneficios son:

  • Conciencia del ancho de banda y uso de la red.
  • Manejo de interrupciones (reanudar, auto-reanudar, pausar, etc.)
  • Descarga de múltiples archivos como trabajos en segundo plano.
  • Capacidad para establecer prioridades de trabajo de descarga.

Descargando un archivo

La forma fundamental de usar Start-BitsTransfer en PowerShell para descargar un archivo es especificar una fuente y un destino. Utilizando el script a continuación, solo necesitas cambiar los valores de $source y $destination según tus requisitos.

$source = 'http://speedtest.tele2.net/100MB.zip'
$destination = 'c:\dload\100MB.zip'
Start-BitsTransfer -Source $source -Destination $destination

Como se puede ver en la demostración a continuación, el archivo se descarga en la ruta c:\dload\100MB.zip.

Downloading a file using Start-BitsTransfer

Supongamos que el destino no está especificado, Start-BitsTransfer descarga y guarda el archivo en el directorio de trabajo actual. Por ejemplo, si ejecutas Start-BitsTransfer desde C:\dload, el archivo se descarga en el mismo directorio.

Para descargas que requieren autenticación, Start-BitsTransfer tiene un parámetro -Credential que acepta un objeto PSCredential.

Descarga de múltiples archivos

Para demostrar la descarga de varios archivos, necesitarás crear un archivo CSV con dos columnas. Llama al archivo filelist.txt. La primera columna debe contener el enlace a la fuente, mientras que la segunda columna debe contener la ruta de destino. El contenido del archivo se vería así.

# source,destination
http://speedtest.tele2.net/1MB.zip,c:\dload\1MB.zip
http://speedtest.tele2.net/10MB.zip,c:\dload\10MB.zip
http://speedtest.tele2.net/100MB.zip,c:\dload\100MB.zip

Relacionado: Manejo de archivos CSV en PowerShell con Import-Csv

Una vez que el archivo CSV esté listo, utiliza el siguiente comando para iniciar la descarga del archivo. El comando importa el archivo CSV utilizando Import-Csv y pasa su contenido a Start-BitsTransfer.

Import-Csv .\filelist.csv | Start-BitsTransfer

Consulta la demostración a continuación para ver cómo funciona el código anterior. Como puedes ver, la descarga comienza y se muestra el progreso de la descarga. Durante el proceso de descarga, el indicador de PowerShell no está disponible.

Starting a synchronous multiple file download

Supongamos que deseas iniciar el proceso de descarga como un trabajo en segundo plano. Para hacerlo, solo tienes que agregar el interruptor -Asynchronous al final del comando Start-BitsTransfer.

Import-Csv .\filelist.csv | Start-BitsTransfer -Asynchronous

Inicialmente, el estado de cada trabajo mostrará “conectando”. La captura de pantalla a continuación muestra el ID de cada trabajo de descarga.

Starting file download as background jobs

Ahora que has iniciado el proceso de descarga, querrás verificar si la descarga se ha completado. Para verificar el estado del trabajo de descarga, utiliza el cmdlet Get-BitsTransfer. Como se muestra a continuación, el estado de los trabajos de descarga ha cambiado a “Transferido”.

Viewing the file download job status

Usando la clase WebClient y la clase HttpClient (.NET Framework)

PowerShell se basa en .NET y su naturaleza le permite aprovechar el poder de .NET en sí mismo. Hay dos clases de .NET que puedes utilizar en PowerShell para descargar archivos; WebClient y HttpClient.

Si quieres saber más sobre estas dos clases .NET de manera más técnica y de desarrollo, podrías comenzar con → Cuándo usar WebClient vs. HttpClient vs. HttpWebRequest. En la próxima sección, aprenderás cómo usar WebClient y HttpClient en PowerShell para descargar archivos de la web.

Descargar un archivo usando System.Net.WebClient

Para usar la clase WebClient, necesitas iniciar un objeto como un tipo System.Net.WebClient. En el ejemplo a continuación, el $webClient es el nuevo objeto System.Net.WebClient. Luego, usando el método DownloadFile() se inicia la descarga del archivo desde la fuente.

Relacionado: Usar Aceleradores de Tipos de Datos de PowerShell para Acelerar la Codificación

Por favor, copia el código a continuación y ejecútalo en tu sesión de PowerShell para probar. Ten en cuenta que no verás ningún progreso o salida en la pantalla a menos que haya un error. Sin embargo, el indicador de PowerShell estará bloqueado hasta que la descarga esté completa.

# Define el enlace de origen y la ruta de destino
$source = 'http://speedtest.tele2.net/10MB.zip'
$destination = 'c:\dload\10MB.zip'
# Crea el nuevo WebClient
$webClient = [System.Net.WebClient]::new()
# Descarga el archivo
$webClient.DownloadFile($source, $destination)

Si la fuente requiere autenticación para permitir la descarga del archivo, puedes usar el código a continuación. La primera línea solicita las credenciales y las guarda en la variable $credentials. El valor de $credential se incluye luego en la solicitud de descarga del archivo.

# Solicitar nombre de usuario y contraseña
$credentials = Get-Credential
$source = 'http://speedtest.tele2.net/10MB.zip'
$destination = 'c:\dload\10MB.zip'
# Crear el nuevo WebClient
$webClient = [System.Net.WebClient]::new()
# Agregar las credenciales
$webClient.Credentials = $credentials
# Descargar el archivo
$webClient.DownloadFile($source, $destination)

De acuerdo con este documento de Microsoft: “No recomendamos el uso de la clase WebClient para nuevos desarrollos. En su lugar, utiliza la clase System.Net.Http.HttpClient.”

Parece que la clase WebClient está obsoleta y la nueva clase que Microsoft respalda es la clase HttpClient. Sin embargo, no te preocupes. La siguiente sección habla sobre cómo usar la clase HttpClient en PowerShell para descargar archivos de la web.

Descargar un archivo usando System.Net.Http.HttpClient

Al igual que con la clase WebClient, primero necesitas crear el System.Net.Http.HttpClient. Usando el código a continuación, se descarga el archivo desde $source hacia $destination. Consulta los comentarios sobre cada línea para saber qué hace cada línea de código.

El código a continuación está en vivo, y puedes probarlo ejecutándolo en tu sesión de PowerShell.

# Establecer la fuente y el destino
$source = 'http://speedtest.tele2.net/10MB.zip'
$destination = 'c:\dload\10MB.zip'
 
# Crear la solicitud de descarga del cliente HTTP
$httpClient = New-Object System.Net.Http.HttpClient
$response = $httpClient.GetAsync($source)
$response.Wait()
 
# Crear un flujo de archivo apuntando al destino del archivo de salida
$outputFileStream = [System.IO.FileStream]::new($destination, [System.IO.FileMode]::Create, [System.IO.FileAccess]::Write)
 
# Transmitir la descarga al flujo de archivo de destino
$downloadTask = $response.Result.Content.CopyToAsync($outputFileStream)
$downloadTask.Wait()
 
# Cerrar el flujo de archivo
$outputFileStream.Close()

En situaciones donde la descarga de un archivo requiere autenticación, necesitas agregar las credenciales al objeto HttpClient. Para incluir una credencial en la solicitud de descarga de archivos, crea un nuevo objeto System.Net.Http.HttpClientHandler para almacenar las credenciales.

Puedes copiar el código a continuación y ejecutarlo en PowerShell para probar. O también puedes ejecutarlo como un script de PowerShell. En este ejemplo, el código se guarda como download-file.ps1.

# Establecer la fuente y el destino
$source = 'http://speedtest.tele2.net/10MB.zip'
$destination = 'c:\dload\10MB.zip'
 
# Solicitar credenciales
$credentials = Get-Credential

# Crear la solicitud de descarga del cliente HTTP con credenciales
$handler = New-Object System.Net.Http.HttpClientHandler
$handler.Credentials = $credentials
$httpClient = New-Object System.Net.Http.HttpClient($handler)
$response = $httpClient.GetAsync($source)
$response.Wait()
 
# Crear un flujo de archivo apuntando al destino del archivo de salida
$outputFileStream = [System.IO.FileStream]::new($destination, [System.IO.FileMode]::Create, [System.IO.FileAccess]::Write)
 
# Transmitir la descarga al flujo de archivo de destino
$downloadTask = $response.Result.Content.CopyToAsync($outputFileStream)
$downloadTask.Wait()
 
# Cerrar el flujo de archivo
$outputFileStream.Close()

La demostración a continuación muestra el resultado al ejecutar el script de PowerShell para descargar el archivo.

Al principio, el directorio solo tiene el archivo de script. Hay un aviso para ingresar el nombre de usuario y la contraseña. Luego, el script procede a descargar el archivo. Después de la descarga, puedes ver que el nuevo archivo está ahora dentro del directorio de destino.

Downloading a file using the .NET HttpClient class

Conclusión

Windows PowerShell y PowerShell Core vienen con capacidades incorporadas para descargar archivos, actuando como una alternativa de PowerShell a wget. Ya sea descargando fuentes protegidas por contraseña, archivos individuales o múltiples, hay una manera en PowerShell.

Los métodos de descarga de archivos cubiertos en este artículo funcionan tanto en Windows PowerShell como en PowerShell Core. Esto significa que estos métodos se aplican tanto a sistemas Windows como a sistemas no Windows, con la exclusión de Start-BitsTransfer.

Y dado que PowerShell es más que un símbolo del sistema, puedes traducir lo que aprendiste en scripts. Para ti, eso significaría una oportunidad para la automatización. No más copiar URL, hacer clic en enlaces y esperar descargas manualmente.

Source:
https://adamtheautomator.com/powershell-download-file/