PSFTP – DownloadFile

Jak poprzednio pokazałem jak wylistować zasoby konta ftp to dziś przedstawię jak pobrać taki zasób z sieci. Do tego celu również wykorzystamy wcześniej użytą klasę .NET, czyli FtpWebRequest.

Jak poprzednio ustawiamy parametry połączenia:

$RequestUri = "ftp://myserverftp.pl/myfolder/file3.zip"
$LocalPath = "c:\file3.zip"
[System.Net.FtpWebRequest]$Request = [System.Net.WebRequest]::Create($RequestUri)
$Request.Credentials = Get-Credential
$Request.EnableSsl = $true
$Request.KeepAlive = $true
$Request.UseBinary = $true
$Request.UsePassive = $true
$Request.Method = [System.Net.WebRequestMethods+FTP]::DownloadFile
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}

Aby było bardziej profesjonalnie zanim pobierzemy plik sprawdźmy czy jest on już dostępny w podanej ścieżce lokalnej. Jeżeli tak to spróbujemy dokończyć jego pobieranie lub zastąpić go poprzez pobranie całości jeszcze raz.

if(Test-Path ($LocalPath))
{
  $FileSize = (Get-Item $LocalPath).Length
  $Title = "A File name already exists in this location."
  $Message = "What do you want to do?"
  $Overwrite = New-Object System.Management.Automation.Host.ChoiceDescription "&Overwrite"
  $Cancel = New-Object System.Management.Automation.Host.ChoiceDescription "&Cancel"
  $Resume = New-Object System.Management.Automation.Host.ChoiceDescription "&Resume"
  $Options = [System.Management.Automation.Host.ChoiceDescription[]]($Cancel, $Overwrite, $Resume)
  $SendFlag = $host.ui.PromptForChoice($Title, $Message, $Options, 2)
}
else
{
  $SendFlag = 1
}

Jeżeli zgadzamy się na pobieranie pliku to ustawiamy wielkość bufora, czyli jak duże partie danych mają być pobierane, a następnie inicjalizujemy sam bufor.

[Int]$BufferSize = 20KB
[Byte[]]$Buffer = New-Object Byte[] $BufferSize

Do celów statystycznych tworzymy zmienne ilości odczytanych danych oraz pobieramy całkowity rozmiar pliku z lokalizacji ftp przy użyciu metody GetFileSize.

$ReadedData = 0
$AllReadedData = 0
[System.Net.FtpWebRequest]$RequestTmp = [System.Net.WebRequest]::Create($RequestUri)
$RequestTmp.Credentials = $Request.Credentials
$RequestTmp.EnableSsl = $Request.EnableSsl
$RequestTmp.KeepAlive = $Request.KeepAlive
$RequestTmp.UseBinary = $Request.UseBinary
$RequestTmp.UsePassive = $Request.UsePassive
$RequestTmp.Method = [System.Net.WebRequestMethods+FTP]::GetFileSize
$ResponseTmp = $RequestTmp.GetResponse()
$TotalData = $ResponseTmp.ContentLength
$ResponseTmp.Close()

W przypadku kontynuowania pobierania otwieramy plik w trybie Append, aby dopisać resztę danych. Modyfikujemy również wartość znacznika zapytania ContentOffset na wielkość obecnie posiadanego pliku na dysku lokalnym, tak aby rozpocząć pobieranie danych od konkretnego bajtu. Jeśli nadpisujemy plik rozpoczynamy wszystko od początku.

if($SendFlag -eq 2)
{
  $File = New-Object IO.FileStream ($LocalPath,[IO.FileMode]::Append)
  $Request.ContentOffset = $FileSize
  $AllReadedData = $FileSize
}
else
{
  $File = New-Object IO.FileStream ($LocalPath,[IO.FileMode]::Create)
}

Ostatecznie wysyłamy zapytanie do serwera I rozpoczynamy odbieranie danych. Dodatkowo możemy użyć komendy Write-Progress, aby zobrazować ile danych pozostało do zakończenia pobierania.

$Response = $Request.GetResponse()
$Stream = $Response.GetResponseStream()

Do{
  $ReadedData=$Stream.Read($Buffer,0,$Buffer.Length)
  $AllReadedData +=$ReadedData
  $File.Write($Buffer,0,$ReadedData)
  Write-Progress -Activity "Download File: $Path" -Status "Downloading:" -Percentcomplete ([int]($AllReadedData/$TotalData * 100))
}
While ($ReadedData -ne 0)

$File.Close()
$Response.Close()

Całość wygląda następująco:

$RequestUri = "ftp://myserverftp.pl/myfolder/file3.zip"
$LocalPath = "C:\file3.zip"
[System.Net.FtpWebRequest]$Request = [System.Net.WebRequest]::Create($RequestUri)
$Request.Credentials = Get-Credential
$Request.EnableSsl = $true
$Request.KeepAlive = $true
$Request.UseBinary = $true
$Request.UsePassive = $true
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}

$Request.Method = [System.Net.WebRequestMethods+FTP]::DownloadFile
if(Test-Path ($LocalPath))
{
  $FileSize = (Get-Item $LocalPath).Length
  $Title = "A File name already exists in this location."
  $Message = "What do you want to do?"
  $Overwrite = New-Object System.Management.Automation.Host.ChoiceDescription "&Overwrite"
  $Cancel = New-Object System.Management.Automation.Host.ChoiceDescription "&Cancel"
  $Resume = New-Object System.Management.Automation.Host.ChoiceDescription "&Resume"
  $Options = [System.Management.Automation.Host.ChoiceDescription[]]($Cancel, $Overwrite, $Resume)
  $SendFlag = $host.ui.PromptForChoice($Title, $Message, $Options, 2)
}
else
{
  $SendFlag = 1
}

if($SendFlag)
{
  [Int]$BufferSize = 20KB
  [Byte[]]$Buffer = New-Object Byte[] $BufferSize

  $ReadedData = 0
  $AllReadedData = 0

  [System.Net.FtpWebRequest]$RequestTmp = [System.Net.WebRequest]::Create($RequestUri)
  $RequestTmp.Credentials = $Request.Credentials
  $RequestTmp.EnableSsl = $Request.EnableSsl
  $RequestTmp.KeepAlive = $Request.KeepAlive
  $RequestTmp.UseBinary = $Request.UseBinary
  $RequestTmp.UsePassive = $Request.UsePassive
  $RequestTmp.Method = [System.Net.WebRequestMethods+FTP]::GetFileSize
  $ResponseTmp = $RequestTmp.GetResponse()
  $TotalData = $ResponseTmp.ContentLength
  $ResponseTmp.Close()

  if($SendFlag -eq 2)
  {
    $File = New-Object IO.FileStream ($LocalPath,[IO.FileMode]::Append)
    $Request.ContentOffset = $FileSize
    $AllReadedData = $FileSize
  }
  else
  {
    $File = New-Object IO.FileStream ($LocalPath,[IO.FileMode]::Create)
  }

  $Response = $Request.GetResponse()
  $Stream = $Response.GetResponseStream()

  Do{
    $ReadedData=$Stream.Read($Buffer,0,$Buffer.Length)
    $AllReadedData +=$ReadedData
    $File.Write($Buffer,0,$ReadedData)
    Write-Progress -Activity "Download File: $RequestUri" -Status "Downloading:" -Percentcomplete ([int]($AllReadedData/$TotalData * 100))
  }
  While ($ReadedData -ne 0)

  $File.Close()
  $Response.Close()
}

Źródła:
http://msdn.microsoft.com/en-us/library/system.net.ftpwebrequest.aspx
http://msdn.microsoft.com/en-us/library/system.net.webrequestmethods.ftp.aspx

http://gallery.technet.microsoft.com/scriptcenter/PowerShell-FTP-Client-db6fe0cb

Reklamy

Skomentuj

Wprowadź swoje dane lub kliknij jedną z tych ikon, aby się zalogować:

Logo WordPress.com

Komentujesz korzystając z konta WordPress.com. Wyloguj / Zmień )

Zdjęcie z Twittera

Komentujesz korzystając z konta Twitter. Wyloguj / Zmień )

Zdjęcie na Facebooku

Komentujesz korzystając z konta Facebook. Wyloguj / Zmień )

Zdjęcie na Google+

Komentujesz korzystając z konta Google+. Wyloguj / Zmień )

Connecting to %s