Sunday, 18 March 2018

Downloading a File With Progress Bar.


        <#
        .Synopsis
            This cmdlet downloads a remote file to the local destination target all the while showing the progress and size of the download.
        .Reference
            https://blogs.msdn.microsoft.com/jasonn/2008/06/13/downloading-files-from-the-internet-in-powershell-with-progress/
        author:jniver
        modified by:picachu010
        #>
        param(
            [CmdletBinding()]

            [Parameter(mandatory=$true,Position=0,
            HelpMessage="Complete url of file.")]
            [ValidateNotNullOrEmpty()]
            [string]$Uri,

            [Parameter(mandatory=$true,
            HelpMessage="Referer url/website.")]
            [ValidateNotNullOrEmpty()]
            [string]$Referer,

            [Parameter(mandatory=$true,Position=1,
            HelpMessage="Full path of destination file with name.")]
            [ValidateScript({-not (Test-Path $_) })]
            [string]$Destination
            )
            Begin{
      
               }
            Process{
          
               ###This code bit was inserted by me.
               $localTempFilePath=[System.IO.Path]::ChangeExtension($Destination,"temp")
               if(Test-Path $localTempFilePath){
                    try{
                        Remove-Item $localTempFilePath
                    }
                    catch{
                        Return $false
                        }
               }
               elseif(-not (Test-Path ([IO.Path]::GetDirectoryName($Destination)))){
                    New-Item ([IO.Path]::GetDirectoryName($Destination)) -ItemType Directory  -Verbose -InformationAction Continue | Out-Null
               }
               ####above code bit was inserted by me.
               $uriObject = New-Object "System.Uri" "$Uri"
               $request = [System.Net.HttpWebRequest]::Create($uriObject)
               if(-not [string]::IsNullOrWhiteSpace($Referer)){
                   $request.Referer="$Referer"
                   }
               $request.set_Timeout(6000) #15 second timeout
               $response = $request.GetResponse()
               if(-not [string]::IsNullOrEmpty($response)){
                   $totalLength = [System.Math]::Floor($response.get_ContentLength()/1024)
                   ###Write-Output "Length is $totalLength KB"
                   $responseStream = $response.GetResponseStream()
                   $responseStream.ReadTimeout=60000###60sec
                    <#<#<##############Appended codes
                    Problem with the code when the download file is less than 1024 bytes.
                     Corrected by doing an If/else statement that checks for file length less than 1024:
                    #>#>#>
                       $responseContentLength = $response.get_ContentLength()
                        if(-not ($responseContentLength -lt 1024))
                        {
                           $totalLength = [System.Math]::Floor($response.get_ContentLength()/1024)
                        }
                        else
                        {
                           $totalLength = [System.Math]::Floor(1024/1024)
                        }
                    #######Appended codes end here
                   $targetStream = New-Object -TypeName System.IO.FileStream -ArgumentList $localTempFilePath, Create
                   $buffer = new-object byte[] 10KB
                   try{
                   $count = $responseStream.Read($buffer,0,$buffer.length)
                   $downloadedBytes = $count
                       while ($count -gt 0)
                       {
                           $targetStream.Write($buffer, 0, $count)
                           $count = $responseStream.Read($buffer,0,$buffer.length)
                           $downloadedBytes = $downloadedBytes + $count
                           ###[System.Math]::Floor($downloadedBytes/1024)
                           Write-Progress -activity "Downloading file '$($Uri.split('/') | Select -Last 1)'" -status "Downloaded ($([System.Math]::Floor($downloadedBytes/1024))K of $($totalLength)K): " -PercentComplete ((([System.Math]::Floor($downloadedBytes/1024)) / $totalLength)  * 100)
                  
                       }
                    }
                    finally{
                        $targetStream.Flush()
                        $targetStream.Close()
                        $targetStream.Dispose()
                        $responseStream.Dispose()
                    }
                   Write-Progress -activity "Finished downloading file '$($Uri.split('/') | Select -Last 1)'"
                   Return $true
               }###if
               else{
                    Return $false
               }
            }###Process
            End{
                  
                if(($totalLength -eq [System.Math]::Floor($downloadedBytes/1024)) -and (0 -ne $downloadedBytes)){
                        Move-Item -Path $localTempFilePath -Destination $Destination
               }
                Remove-Variable "uriObject"
                if($response){
                    Remove-Variable response
                }
                Remove-Variable "request"
            }
       

No comments:

Post a Comment