Давайте разберем несколько основных сценариев работы с FTP с использованием Powershell
-
Загрузка на FTP
$ftp_uri = 'ftp://contoso.com/folder/' $FileName = 'Filename.csv' $LocalPath = 'C:\temp\' $user = 'user' $pass = 'password' # Добавляем новые данные # Задаем имя файла который будет создан на FTP $FTPRequest = [System.Net.FtpWebRequest]::Create( $ftp_uri + $FileName ) $FTPRequest.Credentials = new-object System.Net.NetworkCredential($user, $pass) # Задаем метод для добавления $FTPRequest.Method = [System.Net.WebRequestMethods+Ftp]::UploadFile $FTPRequest.UseBinary = $true $FTPRequest.UsePassive = $true # Считываем файл на локальном компьютере $FileContent = Get-Content -en byte ( $LocalPath + $FileName ) $FTPRequest.ContentLength = $FileContent.Length # Передаем файл на FTP $Run = $FTPRequest.GetRequestStream() $Run.Write($FileContent, 0, $FileContent.Length) # Закрываем соединение $Run.Close() $Run.Dispose()
Обратите внимание что переменная $ftp_uri представляет из себя точку входа, а не конкретный путь.
Потому что каталог в который вы попадете, при подключению к вашему FTP, будет определен настройками вашего FTP аккаунта.
Таким образом, точка входа для $ftp_uri
ftp://contoso.com/folder/
может фактически представлять собой путь
ftp://contoso.com/public_html/files/reports/folder/
-
Скачать с FTP
$ftp_uri = 'ftp://contoso.com/folder/' $LocalPath = 'C:\temp\ftp\' $user = 'user' $pass = 'password' # В отсутствующую папку загрузка не пройдет. Задаем проверку if(!(Test-Path $LocalPath)){ New-Item -ItemType directory -Path $LocalPath } # Получаем список файлов с FTP function Get-FtpDir ($url, $credentials) { $request = [Net.FtpWebRequest]::Create($url) if ($credentials) { $request.Credentials = $credentials } $request.Method = [System.Net.WebRequestMethods+FTP]::ListDirectory (New-Object IO.StreamReader $request.GetResponse().GetResponseStream()).ReadToEnd() -split "`r`n" } $webclient = New-Object System.Net.WebClient $webclient.Credentials = New-Object System.Net.NetworkCredential($user,$pass) $webclient.BaseAddress = $ftp_uri # Выполняем загрузку с возможностью фильтрации Get-FTPDir $ftp_uri $webclient.Credentials | ? { $_ -like "*.csv" } | % { $webClient.DownloadFile( $_,$($LocalPath + $_) ) }
-
Удалить файл с FTP
# Удалить файл с FTP $user='user' $pass='password' $ftp_uri='ftp://contoso.com/folder/Filename.csv' $request = [System.Net.FtpWebRequest]::create($ftp_uri) $request.Credentials = new-object System.Net.NetworkCredential( $user, $pass ) $request.Method = [System.Net.WebRequestMethods+Ftp]::DeleteFile $request.GetResponse()
-
Добавление текста в документ на FTP
Код практически идентичен варианту с загрузкой на FTP, меняется только используемый метод
$ftp_uri = 'ftp://contoso.com/folder/' $FileName = 'Filename.csv' $LocalPath = 'C:\temp\' $user = 'user' $pass = 'password' # Добавляем новые данные # Задаем имя файла который будет создан на FTP $FTPRequest = [System.Net.FtpWebRequest]::Create( $ftp_uri + $FileName ) $FTPRequest.Credentials = new-object System.Net.NetworkCredential($user, $pass) # Задаем метод для добавления $FTPRequest.Method = [System.Net.WebRequestMethods+Ftp]::AppendFile $FTPRequest.UseBinary = $true $FTPRequest.UsePassive = $true # Считываем файл на локальном компьютере $FileContent = Get-Content -en byte ( $LocalPath + $FileName ) $FTPRequest.ContentLength = $FileContent.Length # Передаем файл на FTP $Run = $FTPRequest.GetRequestStream() $Run.Write($FileContent, 0, $FileContent.Length) # Закрываем соединение $Run.Close() $Run.Dispose()
Внимание: Важно не забывать закрыть подключение с FTP,
так как по завершению загрузки, файл не появится на диске до тех пор, пока сессия не будет завершена.
А так же, при инициированном подключении, вы не сможете выполнить новое, и получите ошибку
Возможные ошибки
Исключение при вызове "GetRequestStream" с "0" аргументами: "Невозможно разрешить удаленное имя: 'FILENAME'
Проблема заключается в неправильно заданном формате имени для файла на FTP.
Исключение при вызове "GetRequestStream" с "0" аргументами: "Невозможно соединиться с удаленным сервером"
Проблема, как ни странно, в недоступности вашего сайта.
Выполните Ping, и в случае недоступности сайта, ищите причину возникновения сетевой проблемы.
Спасибо за примеры кода. Однако загрузка на FTP сразу же огорчила, так как при передаче больших файлов они сначала копируются в оперативную память (Get-Content), и ее просто не хватает. Может быть, предложите другой метод?
А «большие», это какого размера?
Попробуйте использовать вместо Get-Content другую конструкцию:
$FileContent = [System.IO.File]::ReadAllBytes( $LocalPath + $FileName )
Нашел альтернативное решение по загрузке на FTP без Get-Content