Get-FtpFile.ps1

function Get-FtpFile()
{
    <#
         .SYNOPSIS
         ����ftp�ļ�, Get-FTPItem ���ļ�̫��,��Ҫ��
          
         .DESCRIPTION
         Get-FtpFile -Username $FtpUsername -Password $FtpPassword -RemoteFile "ftp://thomasmaurer.ch/downloads/files/file.zip" -LocalFile "C:\Temp\file.zip"
     
    #>

    [CmdletBinding()] 
     param (
      [Parameter(Mandatory)][string]$Username,
      [Parameter(Mandatory)][string]$Password,
      [Parameter(Mandatory)][string]$RemoteFile,
      [Parameter(Mandatory)][string]$LocalFile
    )
    

    # $Username = "FTPUSER"
    # $Password = "P@assw0rd"
    # $LocalFile = "C:\Temp\file.zip"
    # $RemoteFile = "ftp://thomasmaurer.ch/downloads/files/file.zip"
    # 3-1 ���� 0 ���Խ��� -1 ����ִ����ϵĽ��
    $tryIfFail = 3

    do
    {
        try
        {
            # GetFileSize
            $GetSizeRequest = [System.Net.FtpWebRequest]::Create($RemoteFile)
            $GetSizeRequest.Credentials = New-Object System.Net.NetworkCredential($Username,$Password)
            $GetSizeRequest.Method = [System.Net.WebRequestMethods+Ftp]::GetFileSize
            $GetSizeRequest.KeepAlive = $false
            $bytes_total = [long]$GetSizeRequest.GetResponse().ContentLength;
            $TotalWriteLength = [long]0;
            
            # Create a FTPWebRequest
            $FTPRequest = [System.Net.FtpWebRequest]::Create($RemoteFile)
            $FTPRequest.Credentials = New-Object System.Net.NetworkCredential($Username,$Password)
            $FTPRequest.Method = [System.Net.WebRequestMethods+Ftp]::DownloadFile
            # ������ģʽ����
            $FTPRequest.UseBinary = $true
            # ������ɺ�ر�����
            $FTPRequest.KeepAlive = $false
            
            if((Test-Path -Path $LocalFile) -eq $false)
            {
                # Create the target file on the local system and the download buffer
                $LocalFileStream = New-Object IO.FileStream ($LocalFile,[IO.FileMode]::Create)
            }else{
                $FTPRequest.ContentOffset = (Get-Item $LocalFile).Length
                $TotalWriteLength += (Get-Item $LocalFile).Length
                $LocalFileStream = New-Object IO.FileStream ($LocalFile,[IO.FileMode]::Append)
            }
            
            # Send the ftp request
            $FTPResponse = $FTPRequest.GetResponse()
            # Get a download stream from the server response
            $ResponseStream = $FTPResponse.GetResponseStream()
            $bufferSize = 1024 * 32
            [byte[]]$ReadBuffer = New-Object byte[] $bufferSize
            # Loop through the download
            do {
                $ReadLength = $ResponseStream.Read($ReadBuffer,0,$ReadBuffer.Length)
                $LocalFileStream.Write($ReadBuffer,0,$ReadLength)
                
                $TotalWriteLength += $ReadLength;
                $PercentComplete = [int][math]::floor($TotalWriteLength / $bytes_total * 100)
                Write-Progress -Activity "download in Progress" -Status "$PercentComplete% Complete: $([int][math]::floor($TotalWriteLength / 1024 / 1024 )) MB $ReadLength $((Get-Random).ToString()[-1])" -PercentComplete $PercentComplete
            }
            while ($ReadLength -ne 0)
            $tryIfFail = -1
        }
        catch{
            $tryIfFail --
            Write-Output $_
            if($tryIfFail -gt 0)
            {
                Write-Output "3 �������"
                Start-Sleep -Seconds 5
            }
            else
            {
                Throw $_
            }
        }    
        finally {
            if($LocalFileStream -ne $null)
            {
                $LocalFileStream.Close();
            }
            if($ResponseStream -ne $null)
            {
                $ResponseStream.Close();
            }
            try {
                # Exception calling "Close" with "0" argument(s): "The remote server returned an error: (451) Local error in processing.
                # �ر� ftp ����ʱ,���ܱ���
                if($FTPResponse -ne $null)
                {
                    $FTPResponse.Close();
                }    
            } catch{}
        }
    }while($tryIfFail -gt 0)
}