Private/WebTools.psm1
|
using module ./Models.psm1 using module ./Console.psm1 using module ./Utilities.psm1 # downloadhelper class dlh { [string]$Id static [PsRecord] $DownloadOptions = @{ ShowProgress = $true ProgressBarLength = { return [int]([ConsoleWriter]::get_ConsoleWidth() * 0.7) } ProgressMessage = [string]::Empty RetryTimeout = 1000 Headers = @{} Proxy = $null Force = $false } dlh() { $this.Id = [Guid]::NewGuid().Guid.replace('-', '').SubString(0, 20) $this.PsObject.Properties.Add([PSScriptProperty]::new('Data', [scriptblock]::Create("`$e = Get-Event -SourceIdentifier $($this.Id) -ea Ignore; if (`$e) { return `$e[-1].SourceEventArgs }; return `$null"))) } [string] GetfileSize([long]$Bytes) { $sizestr = switch ($bytes) { { $bytes -lt 1MB } { "$([Math]::Round($bytes / 1KB, 2)) KB"; break } { $bytes -lt 1GB } { "$([Math]::Round($bytes / 1MB, 2)) MB"; break } { $bytes -lt 1TB } { "$([Math]::Round($bytes / 1GB, 2)) GB"; break } default { "$([Math]::Round($bytes / 1TB, 2)) TB" } } return [string]$sizestr } [string] GetSizeProgress() { if ($null -eq $this.Data) { return [string]::Empty } return $this.GetSizeProgress($this.Data.BytesReceived, $this.Data.TotalBytesToReceive) } [string] GetSizeProgress($r, $t) { return "{0} / {1}" -f $($this.GetfileSize($r)), $($this.GetfileSize($t)) } static [IO.FileInfo] DownloadFile([uri]$url) { $randomSuffix = [Guid]::NewGuid().Guid.subString(15).replace('-', [string]::Join('', (0..9 | Get-Random -Count 1))) return [dlh]::DownloadFile($url, "$(Split-Path $url.AbsolutePath -Leaf)_$randomSuffix") } static [IO.FileInfo] DownloadFile([uri]$url, [string]$outFile) { return [dlh]::DownloadFile($url, $outFile, $false) } static [IO.FileInfo] DownloadFile([uri]$url, [string]$outFile, [bool]$Force) { [ValidateNotNullOrEmpty()][uri]$url = $url [ValidateNotNullOrEmpty()][string]$outFile = $outFile $stream = $null; $fileStream = $null $name = Split-Path $url -Leaf $request = [System.Net.HttpWebRequest]::Create($url) $request.UserAgent = "Mozilla/5.0" $response = $request.GetResponse() $contentLength = $response.ContentLength $stream = $response.GetResponseStream() $buffer = New-Object byte[] 1024 $outPath = [IO.Path]::GetFullPath($outFile) if ([System.IO.Directory]::Exists($outFile)) { if (!$Force) { throw [ArgumentException]::new("Please provide valid file path, not a directory.", "outFile") } $outPath = Join-Path -Path $outFile -ChildPath $name } $Outdir = [IO.Path]::GetDirectoryName($outPath) if (![System.IO.Directory]::Exists($Outdir)) { [void][System.IO.Directory]::CreateDirectory($Outdir) } if ([IO.File]::Exists($outPath)) { if (!$Force) { throw "$outFile already exists" } Remove-Item $outPath -Force -ErrorAction Ignore | Out-Null } $fileStream = [System.IO.FileStream]::new($outPath, [IO.FileMode]::Create, [IO.FileAccess]::ReadWrite, [IO.FileShare]::None) $totalBytesReceived = 0 $totalBytesToReceive = $contentLength $OgForeground = (Get-Variable host).Value.UI.RawUI.ForegroundColor $Progress_Msg = [dlh]::DownloadOptions.ProgressMessage if ([string]::IsNullOrWhiteSpace($Progress_Msg)) { $Progress_Msg = "[+] Downloading $name to $outFile" } Write-Host $Progress_Msg -ForegroundColor Magenta $(Get-Variable host).Value.UI.RawUI.ForegroundColor = [ConsoleColor]::Green while ($totalBytesToReceive -gt 0) { $bytesRead = $stream.Read($buffer, 0, 1024) $totalBytesReceived += $bytesRead $totalBytesToReceive -= $bytesRead $fileStream.Write($buffer, 0, $bytesRead) if ([dlh]::DownloadOptions.ShowProgress) { [int]$PMetric = [math]::Round($totalBytesReceived / $contentLength * 100) [ProgressUtil]::WriteProgressBar($PMetric, $true, [dlh]::DownloadOptions.progressBarLength) } } $(Get-Variable host).Value.UI.RawUI.ForegroundColor = $OgForeground try { Invoke-Command -ScriptBlock { $stream.Close(); $fileStream.Close() } -ErrorAction SilentlyContinue } catch { $null } return (Get-Item $outFile) } static [IO.FileInfo] DownloadFileAsync([uri]$Uri, [string]$OutFile, $dlEvent, [bool]$verbose) { try { $webClient = [System.Net.WebClient]::new() # $webClient.Credentials = $login $task = $webClient.DownloadFileTaskAsync($Uri, $OutFile) Register-ObjectEvent -InputObject $webClient -EventName DownloadProgressChanged -SourceIdentifier $dlEvent.Id | Out-Null $verbose ? (Write-Console " Attempting to download '$Uri' ..." -f SteelBlue) : $null while (!$task.IsCompleted) { if ($null -ne $dlEvent.Data) { $ReceivedData = $dlEvent.Data.BytesReceived $TotalToReceive = $dlEvent.Data.TotalBytesToReceive $TotalPercent = $dlEvent.Data.ProgressPercentage if ($null -ne $ReceivedData) { [ProgressUtil]::WriteProgressBar([int]$TotalPercent, " Downloading : $($dlEvent.GetSizeProgress($ReceivedData, $TotalToReceive))") } } [System.Threading.Thread]::Sleep(50) } } catch { Write-Console $_.Exception.Message -f Salmon throw $_ } finally { $verbose ? ([ProgressUtil]::WriteProgressBar(100, $true, " Downloaded $($dlEvent.GetSizeProgress())", $true)) : $null if ([IO.File]::Exists($OutFile)) { $verbose ? (Write-Console " OutPath: '$OutFile'" -f SteelBlue) : $null } Invoke-Command { $webClient.Dispose(); Unregister-Event -SourceIdentifier $dlEvent.Id -Force -ea Ignore } -ea Ignore } if ([IO.File]::Exists($OutFile)) { return Get-Item $OutFile } else { return [IO.FileInfo]::new($OutFile) } } } |