Kolejnym z ważniejszych elementów zarządzania kontem ftp jest możliwość wysłania pliku do lokalizacji zdalnej. Jak w poprzednich obu przypadkach również wykorzystujemy klasę FtpWebRequest.
Jak poprzednio konfigurujemy połączenie do lokalizacji ftp.
$RequestUri = "ftp://myserverftp.pl/myfolder/file5.zip" $LocalPath = "c:\file5.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}
Sprawdzamy czy plik już istnieje w danej lokalizacji I jeśli tak to sczytujemy jego wielkość. Posłuży nam to do umożliwienia kontynuowania wysyłania pliku w razie nieprzewidzianej awarii.
Try { [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() $FileSize = $ResponseTmp.ContentLength $ResponseTmp.Close() } Catch { $FileSize = 0 }
Jeżeli plik już istnieje, tzn. jego wielkość jest większa od 0 to pytamy się co zrobić. Czy kontynuujemy wysyłanie czy może będziemy wysyłać plik od początku.
if($FileSize) { $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) $Request.Method = [System.Net.WebRequestMethods+FTP]::AppendFile } else { $SendFlag = 1 $Request.Method = [System.Net.WebRequestMethods+FTP]::UploadFile }
Przejdźmy teraz do serca skryptu, czyli otwieramy lokalny plik do odczytu i wysyłamy zapytanie do serwera ftp.
$File = [IO.File]::OpenRead($LocalPath) $Response = $Request.GetRequestStream()
Jak przy odbieraniu danych tak i przy wysyłaniu tworzymy bufor I ustawiamy wielkość wysyłanej paczki danych.
$BufferSize = 20KB [Byte[]]$Buffer = New-Object Byte[] $BufferSize
Ustalamy dane do celów statystycznych.
$ReadedData = 0 $AllReadedData = 0 $TotalData = (Get-Item $LocalPath).Length
I W zależności od wybranego trybu wysyłania danych ustawiamy znacznik na pliku lokalnym na wielkości pliku znajdującego się na serwerze ftp, lub rozpoczynamy cały proces wysyłania od początku.
if($SendFlag -eq 2) { $SeekOrigin = [System.IO.SeekOrigin]::Begin $File.Seek($FileSize,$SeekOrigin) | Out-Null $AllReadedData = $FileSize } Do { $ReadedData = $File.Read($Buffer, 0, $Buffer.Length) $AllReadedData += $ReadedData $Response.Write($Buffer, 0, $ReadedData); Write-Progress -Activity "Upload File: $RequestUri" -Status "Uploading:" -Percentcomplete ([int]($AllReadedData/$TotalData * 100)) } While($ReadedData -gt 0)
Na zakończenie zamykamy plik lokalny oraz zamykamy połączenie.
$File.Close() $Response.Close()
Całość wygląda następująco:
$RequestUri = "ftp://myserverftp.pl/myfolder/file5.zip" $LocalPath = "c:\file5.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} Try { [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() $FileSize = $ResponseTmp.ContentLength $ResponseTmp.Close() } Catch { $FileSize = 0 } if($FileSize) { $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) $Request.Method = [System.Net.WebRequestMethods+FTP]::AppendFile } else { $SendFlag = 1 $Request.Method = [System.Net.WebRequestMethods+FTP]::UploadFile } if($SendFlag) { $File = [IO.File]::OpenRead($LocalPath) $Response = $Request.GetRequestStream(); $BufferSize = 20KB [Byte[]]$Buffer = New-Object Byte[] $BufferSize $ReadedData = 0 $AllReadedData = 0 $TotalData = (Get-Item $LocalPath).Length if($SendFlag -eq 2) { $SeekOrigin = [System.IO.SeekOrigin]::Begin $File.Seek($FileSize,$SeekOrigin) | Out-Null $AllReadedData = $FileSize } Do { $ReadedData = $File.Read($Buffer, 0, $Buffer.Length) $AllReadedData += $ReadedData $Response.Write($Buffer, 0, $ReadedData); Write-Progress -Activity "Upload File: $RequestUri" -Status "Uploading:" -Percentcomplete ([int]($AllReadedData/$TotalData * 100)) } While($ReadedData -gt 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