Xunkar
Xunkar

Reputation: 115

How to download a file as a byte stream?

I am writing a PS script that needs to download a decryption key from a server. However the PS engine parses the file as text when I want to retrieve it as a byte stream. For instance the file contains 84416e8e (ASCII: „AnŽ) and the downloaded file contains 6539653832646439 (ASCII: e9e82dd9) I've tried both Invoke-WebRequest and System.Net.WebClient without success, even when iwr has the option -ContentType "application/octet-stream"

Edit: The issue may not lie with PS, I've noticed that opening the URL to the key through Firefox allows me to download the file correctly, but opening it through Chrome produces the modified version. Is there something I'm missing here?

Upvotes: 3

Views: 6119

Answers (3)

Garric
Garric

Reputation: 724

$wc = New-Object System.Net.WebClient
$bytes = $wc.DownloadData("https://stackoverflow.com/")
#$bytes
Write-Host $bytes.GetType().FullName
$selfDir=(Get-Item -LiteralPath $PSCommandPath ).DirectoryName 
Set-Content "$selfDir\stackoverflow.com.txt" -Value $bytes -Encoding Byte

Upvotes: 0

Theo
Theo

Reputation: 61093

I'm not quite sure if I understand the question correctly, but you can download a binary file and save the bytes in a file.
For demo I used 7zip.exe.

$Response = Invoke-WebRequest -Uri "https://www.7-zip.org/a/7z1900-x64.exe" -OutFile "D:\decryption.key"

or by using BitsTransfer

Import-Module BitsTransfer
Start-BitsTransfer -Source "https://www.7-zip.org/a/7z1900-x64.exe" -Destination "D:\decryption.key"

You can then read this file as a bytearray using:

[byte[]]$bytes = [System.IO.File]::ReadAllBytes("D:\decryption.key")

Or as a string with a 1-to-1 byte mapping using this helper function:

function Import-BinaryString {
    # Imports the bytes of a file to a string that has a
    # 1-to-1 mapping back to the file's original bytes. 
    # Useful for performing binary regular expressions.
    Param (
        [Parameter(Mandatory = $True, ValueFromPipeline = $True, Position = 0)]
        [ValidateScript( { Test-Path $_ -PathType Leaf } )]
        [String]$Path
    )

    $Stream = New-Object System.IO.FileStream -ArgumentList $Path, 'Open', 'Read'

    # Note: Codepage 28591 returns a 1-to-1 char to byte mapping
    $Encoding     = [Text.Encoding]::GetEncoding(28591)
    $StreamReader = New-Object System.IO.StreamReader -ArgumentList $Stream, $Encoding
    $BinaryText   = $StreamReader.ReadToEnd()

    $StreamReader.Close()
    $Stream.Close()

    return $BinaryText
}

and use it with:

$binaryString = Import-BinaryString -Path "D:\decryption.key"

Hope that helps

Upvotes: 3

Tom Blodget
Tom Blodget

Reputation: 20802

The OutFile parameters writes the response body to a file (as binary):

Invoke-WebRequest -OutFile tmp.png -Uri "https://upload.wikimedia.org/wikipedia/en/thumb/1/1d/Information_icon4.svg/40px-Information_icon4.svg.png"  

Perhaps you were processing the response body in a pipeline as text, which you can't do (except after converting to Base64 or similar).

Upvotes: 0

Related Questions