I’ve been migrating several FTP jobs from batch scripts into PowerShell by leveraging PSFTP – below is a quick guide on how you can do the same.
First, you need to download the PSFTP module – https://gallery.technet.microsoft.com/scriptcenter/PowerShell-FTP-Client-db6fe0cb; once downloaded, you need to extract it into your PowerShell modules directory, depending on your OS and environment path configuration, the Modules directory could vary but mine was in C:\Windows\System32\WindowsPowerShell\v1.0\Modules\.
You can also try running $env:PSModulePath.split(‘;‘) to list all of the PowerShell modules paths on your system.
Once you have the module extracted, try to import it in a PowerShell window by running – Import-Module “C:\Windows\System32\WindowsPowerShell\v1.0\Modules\PSFTP\PSFTP.psm1”. If you get no error messages, then the import worked!
You can then run Get-Command -Module PSFTP to see all the cmdlets available under that module:
Get-Command -Module PSFTP CommandType Name Version Source ----------- ---- ------- ------ Alias Move-FTPItem 0.0 PSFTP Alias Receive-FTPItem 0.0 PSFTP Alias Send-FTPItem 0.0 PSFTP Function Add-FTPItem 0.0 PSFTP Function Get-FTPChildItem 0.0 PSFTP Function Get-FTPConnection 0.0 PSFTP Function Get-FTPItem 0.0 PSFTP Function Get-FTPItemSize 0.0 PSFTP Function New-FTPItem 0.0 PSFTP Function Remove-FTPItem 0.0 PSFTP Function Rename-FTPItem 0.0 PSFTP Function Set-FTPConnection 0.0 PSFTP
Each cmdlet is pretty self-explanatory but you can utilize the Get-Help cmdlet to get more info on each cmdlet:
PS Microsoft.PowerShell.Core\FileSystem::> get-help move-ftpitem NAME Rename-FTPItem SYNOPSIS Renames an item in ftp session. Additionally it can be used for move items between folders. SYNTAX Rename-FTPItem [[-Path] <String>] [-NewName] <String> [[-Session] <Object>] [-WhatIf] [-Confirm] [<CommonParameters>] DESCRIPTION The Rename-FTPItem cmdlet changes the name of a specified item. This cmdlet does not affect the content of the item being renamed. RELATED LINKS Get-FTPChildItem #If you need more info, try adding -Detailed at the end or -Examples REMARKS To see the examples, type: "get-help Rename-FTPItem -examples". For more information, type: "get-help Rename-FTPItem -detailed". For technical information, type: "get-help Rename-FTPItem -full". For online help, type: "get-help Rename-FTPItem -online"
You can utilize each cmdlet and write a script to accomplish your FTP/SFTP needs, below are a few functions I created to accomplish some common tasks and by writing them as functions, you can easily reuse them from one script to another:
Connect to an FTP Server:
#This function configures the necessary details for the script to connect to the FTP server function ConnectFTP () { $User = "ftpusername" $Pass = "password" $EncryptedPass = ConvertTo-SecureString -String $Pass -asPlainText -Force $Credentials = New-Object System.Management.Automation.PSCredential($User,$EncryptedPass) $Server = "ftp.servername.com" #Connect to FTP site Set-FTPConnection -Credentials $Credentials -Server $Server -Session MySession -UsePassive } <# TO USE THIS FUNCTION, SIMPLY FILL IN THE DETAILS ABOVE AND CALL THE FUNCTION NAME FROM OUTSIDE THE FUNCTION BRACKETS. #> #Program Start ConnectFTP
OK, so I’m connected, right? How do I know I’m really connected to the FTP server after running the above function?
Here is the same function from earlier with a validation step to another function to verify if the connection was successful and then perform some action if the connection was successful:
#This function configures the necessary details for the script to connect to the FTP server function ConnectFTP () { $User = "ftpusername" $Pass = "password" $EncryptedPass = ConvertTo-SecureString -String $Pass -asPlainText -Force $Credentials = New-Object System.Management.Automation.PSCredential($User,$EncryptedPass) $Server = "ftp.servername.com" #Connect to FTP site #Store the connection output into a variable called $ResponseStatus $ResponseStatus = Set-FTPConnection -Credentials $Credentials -Server $Server -Session MySession -UsePassive #Evaluate the contents of $ResponseStatus using ConnectionStatus function if (ConnectionStatus $ResponseStatus -eq $True) { #If the connection was successful, list the files in the given path Get-FTPChildItem -Session MySession -Path ftp://ftp.servername.com/ftproot/path/ } else { #If the connection failed, write the below string to screen Write-Host "Connection to FTP server failed!" } } #This function will parse the content of a required parameter $ResponseStatus function ConnectionStatus ($ResponseStatus) { #If $ResponseStatus contains the string "*Successfully transferred*", then the connection is considered successful if (($ResponseStatus | Select -ExpandProperty StatusDescription) -like "*Successfully transferred*") { #Success #By returning $True back to the function that called this function, we can step into the if/else condition in the ConnectFTP function return $True } else { #Fail return $False } } #Program Starts Here ConnectFTP
What if you want to upload a file from local storage to the FTP site?
#All you really need to upload a file is something like below Add-FTPItem -Path $FTPPath -Overwrite -LocalPath $FTPFile -Confirm:$False | Out-Null #If you need to see all the available parameters, remember to use Get-Help Add-FTPItem.
We can easily include Add-FTPItem with our existing function(s) to look something like this:
#This function configures the necessary details for the script to connect to the FTP server function ConnectFTP ($FTPPath, $FTPFile) { $User = "ftpusername" $Pass = "password" $EncryptedPass = ConvertTo-SecureString -String $Pass -asPlainText -Force $Credentials = New-Object System.Management.Automation.PSCredential($User,$EncryptedPass) $Server = "ftp.servername.com" #Connect to FTP site #Store the connection output into a variable called $ResponseStatus $ResponseStatus = Set-FTPConnection -Credentials $Credentials -Server $Server -Session MySession -UsePassive #Evaluate the contents of $ResponseStatus using ConnectionStatus function if (ConnectionStatus $ResponseStatus -eq $True) { #If the connection was successful, list the files in the given path #Get-FTPChildItem -Session MySession -Path ftp://ftp.servername.com/ftproot/path/ #If the connection was successful, move the file to FTP site Add-FTPItem -Path $FTPPath -Overwrite -LocalPath $FTPFile -Confirm:$False | Out-Null } else { #If the connection failed, write the below string to screen Write-Host "Connection to FTP server failed!" } } #Program starts here #To call the function now, you have to add parameters to the function call ConnectFTP "ftp://ftp.servername.com/ftproot/path" "/path/to/local/file"
Besides PSFTP, you can also utilize WinSCP to fulfill your FTP/SFTP requirements within PowerShell.
First, you have to download the WinSCP application, you don’t have to install it, but you need the file directory saved somewhere accessible to your script. You can download WinSCP here – https://winscp.net/eng/download.php.
WinSCP on its own can automate and handle FTP/SFTP files; but if you need to use WinSCP within PowerShell, then you can accomplish it by calling the WinSCP COM object by referencing it with an & symbol in your PowerShell script like this “& “C:\Program Files (x86)\WinSCP\WinSCP.com” /command”
With this syntax, you can now leverage any of the WinSCP native commands mentioned here – https://winscp.net/eng/docs/scripting#commands.
Connect to server:
Once you establish the connection successfully, you actually get a WinSCP prompt in your console and all of the mentioned native WinSCP commands are now available to you within that prompt.
PS Microsoft.PowerShell.Core\FileSystem::Khoa> & "C:\Program Files (x86)\WinSCP\WinSCP.com" /command "open ftp://ftpusername:password@ftp.servername.com" Connecting to ftp.servername.com ... Connected Starting the session... Session started. Active session: [1] ftpusername@ftp.servername.com winscp> winscp> winscp>
The same way that we evaluated if we were able to connect successfully with ConnectFTP using PSFTP, we can do similarly with our WinSCP command(s) by assigning the output of a command into a variable:
PS Microsoft.PowerShell.Core\FileSystem::Khoa> $Status = & "C:\Program Files (x86)\WinSCP\WinSCP.com" /command "open ftp://ftpusername:password@ftp.servername.com" exit PS Microsoft.PowerShell.Core\FileSystem::Khoa> $Status Connecting to ftp.locatorsearch.com ... Connected Starting the session... Session started. Active session: [1] ftpusernameh@ftp.servername.com
Hello,
Thank you for this very informative post.
We need to authenticate to the FTP server using a certificate instead of a password. Is this possible with PSFTP or other means?
Thank you.
The powershell module is here: https://www.powershellgallery.com/packages/PSFTP/1.7.0.4
Old link is dead
How to disconnect from the FTP server and free the handles on the files?