FTPS and SFTP are two ways to send and receive files from remote sources. While the name suggests both do the same thing, those are different protocols, in the end, having the same goal. A few weeks back, I had to make sure I can reliably download files from FTPS server using PowerShell, and since I couldn't find anything straightforward to use, I decided to write my own. Transfertto is a new PowerShell module that supports both FTPS and SFTP protocols. Its goal is to be the only module that you need to transfer files to and from FTP/SFTP servers.
To connect and list files on FTP server all you have to do is run 3 line of code
# Anonymous login $Client = Connect-FTP -Server 'speedtest.tele2.net' -Verbose $List = Get-FTPList -Client $Client $List | Format-Table Disconnect-FTP -Client $Client
If you would like to use username and password (most of the cases)
# Login via UserName/Password $Client = Connect-FTP -Server 'test.rebex.net' -Verbose -Username 'demo' -Password 'password' $List = Get-FTPList -Client $Client $List | Format-Table Disconnect-FTP -Client $Client
And finally, the same thing can be achieved using credentials that are a bit safer if you want to store the password instead of using the ClearText option safely.
# Login via credentials $Credential = Get-Credential -UserName 'demo' -Message 'Please enter password' # password is password $Client = Connect-FTP -Server 'test.rebex.net' -Verbose -Credential $Credential $List = Get-FTPList -Client $Client $List | Format-Table Disconnect-FTP -Client $Client
Connect-FTP cmdlet will use default settings when connecting to a given FTP server. Of course, you can define what settings you want to use. All the options such as SSL, Data Connection Type, Encryption Modes, validation of certificates are there.
NAME Connect-FTP SYNTAX Connect-FTP [-Server <string>] [-Credential <pscredential>] [-EncryptionMode {None | Implicit | Explicit | Auto}] [-DataConnectionType {AutoPassive | PASV | PASVEX | EPSV | AutoActive | PORT | EPRT}] [-SslBuffering {Auto | Off | On}] [-DisableDataConnec tionEncryption] [-DisableValidateCertificateRevocation] [-ValidateAnyCertificate] [-Port <int>] [-SendHost] [-SocketKeepAlive] [-AutoConnect] [<CommonParameters>] Connect-FTP [-FtpProfile <FtpProfile>] [<CommonParameters>] Connect-FTP [-Server <string>] [-Username <string>] [-Password <string>] [-EncryptionMode {None | Implicit | Explicit | Auto}] [-DataConnectionType {AutoPassive | PASV | PASVEX | EPSV | AutoActive | PORT | EPRT}] [-SslBuffering {Auto | Off | On}] [-Disa bleDataConnectionEncryption] [-DisableValidateCertificateRevocation] [-ValidateAnyCertificate] [-Port <int>] [-SendHost] [-SocketKeepAlive] [-AutoConnect] [<CommonParameters>] ALIASES None REMARKS None
It's also possible to run Request-FTPConfiguration and have the module test for you all different combinations that work with a given FTP server.
# Login via UserName/Password $ProfileFtp1 = Request-FTPConfiguration -Server 'test.rebex.net' -Verbose -Username 'demo' -Password 'password' $ProfileFtp1 | Format-Table # Anonymous login $ProfileFtp2 = Request-FTPConfiguration -Server 'speedtest.tele2.net' -Verbose $ProfileFtp2 | Format-Table
Profiles from Request-FTPConfiguration can then be directly used by the Connect-FTP cmdlet.
# Login via UserName/Password via autodetect - keep in mind using Connect-FTP directly will be faster... $ProfileFtp1 = Request-FTPConfiguration -Server 'test.rebex.net' -Verbose -Username 'demo' -Password 'password' $ProfileFtp1 | Format-Table # use first profile $Client = Connect-FTP -FtpProfile $ProfileFtp1[0] Get-FTPList -Client $Client | Format-Table Disconnect-FTP -Client $Client
Or you can simply use the AutoConnect switch, which will go thru those options directly before connecting.
# Login via UserName/Password via autoconnect - this will try all options and connect, while displaying Verbose what settings were used to achieve connection # Useful for trying out every possible combination $Client = Connect-FTP -Server 'test.rebex.net' -Username 'demo' -Password 'password' -AutoConnect -Verbose Get-FTPList -Client $Client | Format-Table Disconnect-FTP -Client $Client
Now that you know how to connect to an FTP server let's check how you can upload some files to the FTP server. As you can see below, I'm first connecting to the FTP server, then listing current files and checking the content, then checking the directory's content within the FTP server. Finally, I get a list of files stored locally and upload them one by one into the FTP server by using the Send-FTPFile cmdlet. You can either use this command to send file by file, including auto-creation of the remote directory or upload all files at once.
$Client = Connect-FTP -Server '192.168.241.187' -Verbose -Username 'test' -Password 'BiPassword90A' -EncryptionMode Explicit -ValidateAnyCertificate # List files $List = Get-FTPList -Client $Client $List | Format-Table # List files within Temporary directory $List = Get-FTPList -Client $Client -Path '/Temporary' $List | Format-Table # Get local files $ListFiles = Get-ChildItem -LiteralPath $PSScriptRoot\Upload # Upload file by file foreach ($File in $ListFiles) { # To temporary Send-FTPFile -Client $Client -LocalPath $File.FullName -RemotePath "/Temporary/$($File.Name)" -RemoteExists Overwrite # to directory within Temporary that may not exists Send-FTPFile -Client $Client -LocalPath $File.FullName -RemotePath "/Temporary/CreateDir/$($File.Name)" -RemoteExists Skip -CreateRemoteDirectory } # Upload all files at once to FTP Send-FTPFile -Client $Client -LocalPath $ListFiles.FullName -RemotePath "/Temporary" -RemoteExists Overwrite Disconnect-FTP -Client $Client
Similarly, if you want to download files from an FTP server, you would connect to FTP, get a list of files on FTP, find the files you need, and download those files – all of that in less than 10 lines of code.
# Connect to FTP $Client = Connect-FTP -Server 'test.rebex.net' -Verbose -Username 'demo' -Password 'password' # Get list of files on FTP $List = Get-FTPList -Client $Client -Path '/pub/example' # Find latest file on FTP server $FindLatestFile = $List | Where-Object { $_.Type -eq 'File' } | Sort-Object -Property Modified -Descending | Select-Object -First 2 # Download that file foreach ($RemoteFile in $FindLatestFile) { Receive-FTPFile -Client $Client -RemoteFile $RemoteFile -LocalPath "$PSScriptRoot\Download\$($RemoteFile.Name)" -LocalExists Overwrite -VerifyOptions Retry, None } # Download multiple files into directory Receive-FTPFile -Client $Client -RemoteFile $FindLatestFile -LocalPath "$PSScriptRoot\Download" -LocalExists Overwrite -VerifyOptions Retry, None # Disconnect Disconnect-FTP -Client $Client
Of course, uploading and downloading files from an FTP server using PowerShell is not the only thing you can do on an FTP server. You may want to get or set permissions, or for example, if something is not working correctly, you may want to see what's happening behind the scenes and look at what the FTP server is reporting.
# If you want to track responses from FTP Set-FTPTracing -Enable -DisplayConsole $Client = Connect-FTP -Server '192.168.241.187' -Verbose -Username 'test' -Password 'BiPassword90A' -EncryptionMode Explicit -ValidateAnyCertificate # List files Get-FTPList -Client $Client -Path '/Temporary' | Format-Table * Get-FTPChmod -Client $Client -RemotePath '/Temporary' # Set / Read Chmod - you need to have permissions for this to work properly Set-FTPChmod -Client $Client -RemotePath '/Temporary/OrgChart (1).pdf' -Permissions 666 Set-FTPChmod -Client $Client -RemotePath '/Temporary/CreateDir' -Permissions 666 # Set / Read Chmod - you need to have permissions for this to work properly Get-FTPChmod -Client $Client -RemotePath '/Temporary/OrgChart (1).pdf' Get-FTPChmod -Client $Client -RemotePath '/Temporary/CreateDir' Set-FTPTracing -Disable
Using Set-FTPTracing to enable or disable visibility of commands being sent to the FTP server can be very useful to track what is actually happening behind the scenes. If you want to get current permissions of a file or folder, you will use Get-FTPChmod to set permissions Set-FTPChmod. Of course – to change something, you may need to have permissions first. Finally, if you would like to test if the file exists on the source, you can do this using the Test-FTPFile command.
$Client = Connect-FTP -Server '192.168.241.187' -Verbose -Username 'test' -Password 'BiPassword90A' -EncryptionMode Explicit -ValidateAnyCertificate # List files Test-FTPFile -Client $Client -RemotePath '/Temporary'
Of course, there are many other things you can do on an FTP server. I've created cmdlets to move FTP file (Move-FTPFile), move FTP directory (Move-FTPDirectory), remove files or folders (Remove-FTPDirectory/Remove-FTPFile), and it's all mostly self-explanatory. But one thing that could be useful if your FTP server supports it – is FXP transfer. FXP transfer is basically a way to transfer files between two FTP servers without utilizing your machine at all. You tell one FTP server that it should connect to the other FTP server and transfer the files without being involved. This allows you to send files without storing them locally on your own machine. You would use Start-FXPFileTransfer or Start-FXPDirectoryTransfer commands. But to tell you the truth, I've not tested if they work – as my servers – don't support it.
Similar code can be used for SFTP protocol. Connecting to SFTP, listing SFTP files/folders is just three lines of code.
$SftpClient = Connect-SFTP -Server '192.168.240.29' -Username 'przemek' -Password 'YourPassword' Get-SFTPList -SftpClient $SftpClient | Format-Table Get-SFTPList -SftpClient $SftpClient -Path "/home" | Format-Table Disconnect-SFTP -SftpClient $SftpClient
Since SFTP is based on SSH, there's much less option to play with for Connect-SFTP configuration. Uploading files is as easy as using one line of code.
$SftpClient = Connect-SFTP -Server '192.168.241.187' -Verbose -Username 'test' -Password 'BiPassword90A' Get-SFTPList -SftpClient $SftpClient | Format-Table Get-SFTPList -SftpClient $SftpClient -Path "/Temporary" | Format-Table * $ListFiles = Get-ChildItem -LiteralPath $PSScriptRoot\Upload foreach ($File in $ListFiles) { Send-SFTPFile -SftpClient $SftpClient -LocalPath $File.FullName -RemotePath "/Temporary/$($File.Name)" -AllowOverride } Disconnect-SFTP -SftpClient $SftpClient
Similarly, as you used the code above (Send-SFTPFile) to upload files, you can also download files from SFTP using Receive-SFTPFile.
$SftpClient = Connect-SFTP -Server '192.168.240.29' -Username 'przemek' -Password 'BigMouth88nA!!A00!A' Get-SFTPList -SftpClient $SftpClient | Format-Table Get-SFTPList -SftpClient $SftpClient -Path "/home" | Format-Table Receive-SFTPFile -SftpClient $SftpClient -RemotePath '/home/przemek/test1.txt' -LocalPath "$PSScriptRoot\Downloads\mmm.txt" Send-SFTPFile -SftpClient $SftpClient -LocalPath "$PSScriptRoot\Downloads\mmm.txt" -RemotePath '/home/przemek/mmm.txt' -AllowOverride
You can connect, list, upload, download, and disconnect from the SFTP server with just five commands.
If that's not enough, you can always connect directly to SSH and execute commands that can help with additional automation steps that can't be done using transfer protocol.
$SshClient = Connect-SSH -Server '192.168.240.29' -Username 'przemek' -Password 'sdsd' $Command = { 'cd /' 'ls -la' 'cd /etc' 'ls -la' } $SshCommand = Send-SSHCommand -SSHClient $SshClient -Command $Command -Verbose $SshCommand $Command = { 'cat /etc/hosts.allow' } $SshCommand = Send-SSHCommand -SSHClient $SshClient -Command $Command -Verbose $SshCommand
While I have not spent a lot of time on this functionality, it does add some fun to this module.
To run it, just install it from PowerShellGallery, and you're good. If you are not an administrator, you can use this module within the scope of the current user.
Install-Module Transferetto -Force -Scope CurrentUser
If, however, you would like to make sure the module is available machine-wide, you can do this without providing scope.
Install-Module Transferetto -Force
All source codes are available on GitHub. If you have an issue, feature request, problem, please use GitHub as a way to reach for support. As I have limited time, reaching out via email doesn't bring many results. As with many of my other PowerShell modules, it's always a work in progress, and not everything is 100% finished.