Как загружать файлы по FTP с помощью PowerShell
Протокол передачи файлов (FTP) — это распространенная служба, используемая для передачи файлов между клиентами и серверами. Часто полезно автоматизировать эту передачу файлов, и сценарии PowerShell могут пригодиться для ускорения этого процесса.
Как использовать FTP в PowerShell
В PowerShell существует несколько различных способов передачи данных по FTP.
Самый простой способ — использовать WebClient.UploadFile
. PowerShell — это объектно-ориентированный язык сценариев, и у вас есть полный доступ к стандартным библиотекам .NET
с помощью New-Object
. При этом вы можете создать новый WebClient
, установить для него учетные данные и загрузить файл.
$client = New-Object System.Net.WebClient $client.Credentials = New-Object System.Net.NetworkCredential("username", "password") $client.UploadFile("ftp://example.com/path/archive.zip", "C:\archive.zip")
Это будет работать нормально, но не сможет обрабатывать зашифрованные запросы TLS/SSL или выполнять «активные» FTP-передачи. Использование FtpWebRequest
, описанное ниже, решит эту проблему.
Однако не рекомендуется хранить имя пользователя и пароль в сценарии, особенно если этот сценарий фиксируется в общем репозитории Git. Вместо этого вы можете установить переменные среды, такие как FtpUsername
, и получить к ним доступ в скрипте.
function uploadToFTPServer($remote, $local) { $client = New-Object System.Net.WebClient $client.Credentials = New-Object System.Net.NetworkCredential($Env:FtpUsername, $Env:FtpPassword) $client.UploadFile($remote, $local) } uploadToFTPServer "ftp://example.com/path/archive.zip", "C:\archive.zip"
Превращение этого в функцию также позволит вам легко выполнять несколько переводов, вызывая функцию с разными параметрами.
Расширенные возможности FTP-передачи с помощью PowerShell
Если вам нужно больше контроля, вы должны использовать FtpWebRequest
. Это будет поддерживать передачу TLS, а также позволит вам отключить пассивный режим. Самый простой способ его использования — открыть файловый поток и скопировать его в FTP-поток.
function uploadToFTPServer($remote, $local) { $request = [System.Net.FtpWebRequest]::Create($remote) $request.Credentials = New-Object System.Net.NetworkCredential($Env:FtpUsername, $Env:FtpPassword) $request.Method = [System.Net.WebRequestMethods+Ftp]::UploadFile $request.UsePassive = $true $fileStream = [System.IO.File]::OpenRead($local) $ftpStream = $request.GetRequestStream() $fileStream.CopyTo($ftpStream) $ftpStream.Dispose() $fileStream.Dispose() } uploadToFTPServer "ftp://example.com/archive.zip" "C:\archive.zip"
Поскольку он использует файловые потоки, а не считывает все байты, это позволяет лучше работать с большими передачами файлов.
Отправка SFTP-переводов с помощью Posh-SSH
SFTP — это альтернативный FTP-протокол, работающий через SSH. Его немного сложнее использовать, чем обычный FTP, так как вы не можете просто отправить имя пользователя и пароль, и он не поддерживается родной оболочкой PowerShell.
Вам потребуется установить пакет Posh-SSH
для связи по SFTP:
Install-Module -Name Posh-SSH
Затем вы сможете начать новый сеанс, используя новый объект учетных данных. Это работает так же, как передача веб-запросов, за исключением того, что вам также нужно будет закрыть сеанс в конце.
Import-Module Posh-SSH $Password = ConvertTo-SecureString $Env:FtpPassword -AsPlainText -Force $Credential = New-Object System.Management.Automation.PSCredential ($Env:FtpUsername, $Password) $FilePath = "C:\archive.zip" $SftpPath = '/folder' $ThisSession = New-SFTPSession -ComputerName '1.2.3.4' -Credential $Credential Set-SFTPFile -SessionId ($ThisSession).SessionId -LocalFile $FilePath -RemotePath $SftpPath Get-SFTPSession | % { Remove-SFTPSession -SessionId ($_.SessionId) }
Отправка огромных файлов с индикатором выполнения в PowerShell
Использовать CopyTo
файлового потока просто, но для длительных передач вам может потребоваться какой-либо мониторинг хода выполнения. Это немного сложно добавить, так как вам придется копировать потоки самостоятельно, но это хорошо работает со следующим скриптом:
$request = [Net.WebRequest]::Create("ftp://example.com/path/archive.zip") $request.Credentials = New-Object System.Net.NetworkCredential($Env:FtpUsername, $Env:FtpPassword) $request.Method = [System.Net.WebRequestMethods+Ftp]::UploadFile $fileStream = [System.IO.File]::OpenRead("C:\archive.zip") $ftpStream = $request.GetRequestStream() $buffer = New-Object Byte[] 10240 while (($read = $fileStream.Read($buffer, 0, $buffer.Length)) -gt 0) { $ftpStream.Write($buffer, 0, $read) $pct = ($fileStream.Position / $fileStream.Length) Write-Progress ` -Activity "Uploading" -Status ("{0:P0} complete:" -f $pct) ` -PercentComplete ($pct * 100) } $ftpStream.Dispose() $fileStream.Dispose()