uNo KaWaL
uNo KaWaL

Reputation: 9

Powershell - download image from a dynamic link

We have a server capacity reporting site that runs under Cognos.

The site has a logon for authentication. Then just input the server/hostname and you will be presented with the different links for the reports such as CPU/Memory & Disk utilizations.

The site produces an image/graph of the utilization. I want to be able to download/save the image.

So far what i have is below ..

## Initialize variables
$username = "TAUser1" 
$password = "Pas$W0rd" 
$ie = New-Object -com InternetExplorer.Application 
$ie.visible=$true
$Folder = "D:\Data\Scripts\Cognos\Images\"

## Link to CPU Util
$Url1 = "https://XYZ..com:12345/tarf/servlet/dispatch?b_action=cognosViewer&ui.action=run&ui.object=%2fcontent%2fpackage%5b%40name%3d%27Windows_OS_Reports%27%5d%2freport%5b%40name%3d%27WI_NT_ProcessorTotal%27%5d&ui.name=WI_NT_ProcessorTotal&run.outputFormat=&run.prompt=false&p_TCRDateFilter=<selectChoices><selectOption useValue=%22%20between cast( cast(_add_days(current_date,-30) as char(10) ) || ' 00:00:00.000' as TIMESTAMP) and cast( cast(   current_date  as char(10) )  || '23:59:59.999' as TIMESTAMP)%22 displayValue='Last 30 Days'/></selectChoices>&p_Param_Server=Primary:MyServer:NT"

## Open URL & Login 
$ie.navigate($Url1) 
while($ie.ReadyState -ne 4) {start-sleep -m 200} 
$ie.document.getElementById("CAMUsername").value= "$username" 
$ie.document.getElementById("CAMPassword").value = "$password" 
$ie.document.getElementById("cmdOK").Click()
start-sleep 20 
## -- after logon the image/chart of the CPU util is shown

## Get the link for the image/chart
$sources = $ie.document.getElementsByTagName('img') | Select-Object -ExpandProperty src -Last 1

## The link looks something like this .. dynamic?
# >> https://XYZ..com:12345/tarf/servlet/dispatch?b_action=dc&f=b3V0cHV0MzMyMTQwMTY5NDExMzQ3OTE_&k=FAAAAMoy9pBPf6OTheytEtxRbuihvYL-9uQyBEGBYwDFXnprWn6KQpc5Zig_&s=FAAAAMoy9pBPf6OTheytEtxRbuihvYL-JbPEBnix8kFdZ2*-LnYbI3NszrU_&did=2013-03-21-08.24.10.711381

## I am able to go/navigate to this link, show me the image.
$ie.navigate($sources) 

## The image on that link ($sources) is the one i want to be able to download.

Please let me know if you have any ideas. Thank you in advance.

Upvotes: 1

Views: 1527

Answers (1)

David Anderson
David Anderson

Reputation: 8616

I've had great success using PowerShell's built-in Invoke-WebRequest with its SessionVariable/WebSession flags for things like this.

Here is an example of how you might use it for your scenario. I have not tested this as I do not have access to a Cognos server. You may need to adapt it but the basics are here.

# This is needed for UrlEncode.
[Reflection.Assembly]::LoadWithPartialName("System.Web") | out-null

# These are the posted items. Expand if necessary. 
# You may need "cmdOk" = <something>;
$postItems = @{
    "CAMUsername" = $username;
    "CAMPassword" = $password;
}

# This builds the POST data for the login.
$encodedItems = $postItems.Keys | foreach { "$([System.Web.HttpUtility]::UrlEncode($_))=$([System.Web.HttpUtility]::UrlEncode($postItems[$_]))" }
$body = $encodedItems -join "&"

# Passing SessionVariable lets us keep the requests under one "browser" session.
$mainPage = Invoke-WebRequest $url -SessionVariable $session -Body $body -Method Post

# PowerShell's WebRequest provides a convenient Images array with all of the images.  Query this as necessary.
$imgSrc = $mainPage.Images | Select-Object -ExpandProperty src -Last 1    
$imgName = [System.IO.Path]::GetFileName($p.Images[0].src)
$imgName += ".png" # Append the correct extension here!

# Finally, grab the img using the logged in session and write it out to a file as byte encoded. 
$outPath = Join-Path $Folder $imgName
Invoke-WebRequest $imgSrc -WebSession $session | Select -ExpandProperty Content | Set-Content -Encoding Byte $outPath

The magic is in passing -SessionVariable $session to the first request. This kicks off a session as if you were using a browser so you can do things like logging in. You pass this to future requests using -WebSession $session.

Depending on how the server's login feature works, you may need to kick off an earlier Invoke-WebRequest directly to the login page and then grab appropriate form items from there using the WebRequest Forms member. For example, I've encountered pages that generate a serverside token that is expected to be passed in with the login credentials. I'd suggest using your browser's developer tools to check exactly what is being posted and reproduce this using $postItems.

Upvotes: 1

Related Questions