I use a software called Belarc Avisor, that provides an html output of all the hardware-software details including licenses/keys/serials of installed software in an html format. I usually create this report from this software either on a new PC or before formatting a PC. However the chrome exported file uses a separate folder for images, and I need a standalone html file with all the details and images (inclding css styles of the html report).
I presently had to replace the images in notepad++ with their base64 code that was generated from an online website. I'm looking for an alternative way to do this in either batch script or Powershell. I found two stackoverflow questions {q1}, {q2}, and a {blog-post}, and have the following code:
$original_file = 'path\filename.html'
$destination_file = 'path\filename.new.html'
(Get-Content $original_file) | Foreach-IMG-SELECTOR-Object {
$path = $_ SOURCE-TAG-SELECTOR `
-replace $path, [convert]::ToBase64String((get-content $path -encoding byte))
} | Set-Content $destination_file
In the Foreach-Object
, maybe the object could be selected by the html img tag? If yes, then the base64 conversion would be quite easy!
for converting to base64, the string is:
[convert]::ToBase64String((get-content $path -encoding byte))
where $path
is the path to the image. Could be just copied from the <img src="">
tag.
I just read that Windows 10 has Powershell 5.0, so I thought I could create a batch file for creating this.
So if the img
tags & the src
attribute can be selected, they only have to be replaced by their base64 tags.
Modified version of the Answer
The answer provided by Alexendar is invalid because during the loop, the attribute-Value is being set to the #Document, while it should be set to the current node. After searching online and reading the Powershell console, I found that this could be solved by Selecting the current node via XPath. Here's the modified answer:
Import-Module -Name "C:\HtmlAgilityPack.1.4.6\Net40\HtmlAgilityPack.dll" # Change to your actual path
function Convert_to_Base64 ($sImgFile)
{
#$sImgFile = "C:\image.jpg" # Change to your actual path
$oImgFormat = [System.Drawing.Imaging.ImageFormat]::Gif # Change to your format
$oImage = [System.Drawing.Image]::FromFile($sImgFile)
$oMemoryStream = New-Object -TypeName System.IO.MemoryStream
$oImage.Save($oMemoryStream, $oImgFormat)
$cImgBytes = [Byte[]]($oMemoryStream.ToArray())
$sBase64 = [System.Convert]::ToBase64String($cImgBytes)
$sBase64
}
$sInFile = "C:\Users\USER\Desktop\BelarcAdvisor win10\Belarc Advisor Computer Profile.html" # Change to your actual path
$sOutFile = "D:\Win10-Belarc.html" # Change to your actual path
$sPathBase = "C:\Users\USER\Desktop\BelarcAdvisor win10\"
$sXpath = "//img"
$sAttributeName = "src"
$oHtmlDocument = New-Object -TypeName HtmlAgilityPack.HtmlDocument
$oHtmlDocument.Load($sInFile)
$oHtmlDocument.DocumentNode.SelectNodes($sXpath) | ForEach-Object {
# If you need to download the image, here's how you can extract the image
# URI (note that it may be realtive, not absolute):
$sVarXPath = $_ #To get the Current Node and then later get Attributes + XPathXPath from this node variable.
#$sVarXPath.XPath
$sSrcPath = $sVarXPath.get_Attributes() `
| Where-Object { $_.Name -eq $sAttributeName } `
| Select-Object -ExpandProperty "Value"
# Assembling absolute URI:
$sUri = Join-Path -Path $sPathBase -ChildPath $sSrcPath.substring(2) #substring for "./" in the src string of the img in subfolder.
#$sUri
# Now you can d/l the image: Invoke-WebRequest -Uri $sUri
#[System.Drawing.Image]::FromFile($sUri)
# Put your Base64 conversion code here.
$sBase64 = Convert_to_Base64($sUri)
$sSrcValue = "data:image/png;base64," + $sBase64
$oHtmlDocument.DocumentNode.SelectNodes($sVarXPath.XPath).SetAttributeValue($sAttributeName, $sSrcValue)
#$oHtmlDocument.DocumentNode.SelectNodes($sVarXPath.XPath).GetAttributeValue($sAttributeName, "")
}
#$oHtmlDocument.DocumentNode.SelectNodes($sXpath) | foreach-object { write-output $_ }
$oHtmlDocument.Save($sOutFile)