PowerShell

Easy way to connect to FTPS and SFTP using PowerShell

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.

Multiple ways to connect to FTP/FTPS server using PowerShell

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
Uploading / Downloading FTP files from FTP/FTPS server using PowerShell

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'
Other FTP/FTPS commands

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.

Connecting to SFTP server using PowerShell

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.

Executing SSH commands from PowerShell

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.

Transferetto - Installing FTP/SFTP PowerShell 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.

Przemyslaw Klys

System Architect with over 14 years of experience in the IT field. Skilled, among others, in Active Directory, Microsoft Exchange and Office 365. Profoundly interested in PowerShell. Software geek.

Share
Published by
Przemyslaw Klys

Recent Posts

Upgrade Azure Active Directory Connect fails with unexpected error

Today, I made the decision to upgrade my test environment and update the version of…

2 months ago

Mastering Active Directory Hygiene: Automating Stale Computer Cleanup with CleanupMonster

Have you ever looked at your Active Directory and wondered, "Why do I still have…

3 months ago

Active Directory Replication Summary to your Email or Microsoft Teams

Active Directory replication is a critical process that ensures the consistent and up-to-date state of…

7 months ago

Syncing Global Address List (GAL) to personal contacts and between Office 365 tenants with PowerShell

Hey there! Today, I wanted to introduce you to one of the small but excellent…

12 months ago

Active Directory Health Check using Microsoft Entra Connect Health Service

Active Directory (AD) is crucial in managing identities and resources within an organization. Ensuring its…

1 year ago

Seamless HTML Report Creation: Harness the Power of Markdown with PSWriteHTML PowerShell Module

In today's digital age, the ability to create compelling and informative HTML reports and documents…

1 year ago