Interacting with FTP/SFTP using Powershell

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

 

 

 

0 0 votes
Article Rating
Subscribe
Notify of
guest
3 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Marc
Marc
3 years ago

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.

Jens
Jens
3 years ago

The powershell module is here: https://www.powershellgallery.com/packages/PSFTP/1.7.0.4
Old link is dead

Jacques
Jacques
3 years ago

How to disconnect from the FTP server and free the handles on the files?