Przy okazji prac nad http://msmvp.pl dość regularnie musiałem przerzucać bazkę SQL CE z jednego miejsca w drugie (z aplikacji do zbierania danych w "publiczny" portal), przez FTP. A nawet FTPS. Z początku robiłem to ręcznie, ale wiadomo: gdy jakieś czynności zaczynają nużyć to warto je zautomatyzować.
W pracy jestem czasami wystawiony na Powershell, sam także w nim momentami popisuję, i muszę przyznać, że moja początkowa antypatia do tego narzędzia mija. Bez zastanowienia więc wybrałem właśnie PS jako środek do w pełni zautomatyzowanego przerzucania pliku z jednej aplikacji do drugiej.
Podstawowa komunikacja przez FTP jest w .NET dość wygodnie zaimplementowana w klasie FtpWebRequest i sprawnie poszło mi zrobienie tego co trzeba po gołym FTP. Jednak FTP tylko tylko FTPS bez S, jak Psikuta, i to S musiałem dodać. Problem pojawił się, gdy chciałem zaakceptować certyfikat serwera, który domyślnie był odrzucany. Poniżej funkcja tworząca żądanie FTPS:
function prepareRequest{
param([string]$uri)
$ftprequest = [System.Net.FtpWebRequest]::create($uri)
$ftprequest.Credentials = New-Object System.Net.NetworkCredential($username,$password)
$ftprequest.EnableSsl = $true
$ftprequest.UseBinary = $true
$ftprequest.KeepAlive = $false
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}
return $ftprequest
}
Kluczem była odpowiednia konfiguracja ServerCertificateValidationCallback. W C# robiłem to wielokrotnie, ale w Powershell z niezrozumiałych względów jakoś… utknąłem:).
Wykorzystanie funkcji do ściągnięcia pliku:
$ftprequest = prepareRequest($sourceuri);
$ftprequest.Method = [System.Net.WebRequestMethods+Ftp]::DownloadFile
$ftpresponse = $ftprequest.GetResponse()
$responsestream = $ftpresponse.GetResponseStream()
$targetfile = New-Object IO.FileStream ($targetpath,[IO.FileMode]::Create)
[byte[]]$readbuffer = New-Object byte[] 1024
do{
$readlength = $responsestream.Read($readbuffer,0,1024)
$targetfile.Write($readbuffer,0,$readlength)
}
while ($readlength -ne 0)
$targetfile.close()
Pełen skrypt można obejrzeć na Githubie. Obok trzymam sobie *.bat z parametrami w postaci mojego loginu i hasła do Webio, jednak z oczywistych względów jest on dodany do .gitignore.