Migrating documents via SFTP

A previous post covered how to programmatically download documents via FTP: How to download from FTP programmatically
If FTP over SSL is needed, that’s just a property to enable SSL:

$request = [Net.WebRequest]::Create($url)
$request.EnableSsl = $true  #enable SSL

Sometimes there is a need to access and download documents via SFTP. That’s a completely different beast. To do that, I utilize the open source WinSCP. Both the .exe and DLL are needed, and can be co-located with the script.  Read more about WinSCP.

In PowerShell, just load the type library:

Add-Type -Path "WinSCPnet.dll"

Then set up the session. Below I chose to use the actual SSH Host Key Fingerprint:

$sessionOptions = New-Object WinSCP.SessionOptions
$sessionOptions.Protocol = [WinSCP.Protocol]::Sftp
$sessionOptions.HostName = "sftp.myDomain.com"
$sessionOptions.UserName = "username"
$sessionOptions.Password = 'password'
$sessionOptions.SshHostKeyFingerprint = "ssh-rsa 1024 96:9b:ed:1f:66:8b:13:64:c3:ed:11:e0:27:68:62:67"

If you don’t want to bother confirming the crypto key, just set this property instead:

$sessionOptions.GiveUpSecurityAndAcceptAnySshHostKey = "True"

Then create a new session and open it:

$session = New-Object WinSCP.Session
$session.Open($sessionOptions)

Note $session.output contains all the useful FTP transactions, which you can log.

You also have the option to capture debugging information and set the debugging level:

$session.DebugLogPath = "D:\plautj\mypath"
$session.SessionLogPath = "D:\plautj\mypath2"
$session.DebugLevel = 1

Once the connection is established, use the session to:
1. Capture the directory listing: $directory = $session.ListDirectory($FTPDir)
2. Download files: $session.GetFiles($remotePath, $localPath).Check()
3. Delete files: $session.RemoveFiles($remotePath).Check()

Below is the full script to connect to SFTP, download all files, and delete them from the FTP Server:

$DeleteSource = $true;
$DestLocation = "\\DestinationServer\Location\";
$FTPDir = "/USERS/MyDir"
#todo
$ok = $true;
try
{
$ok = test-path $destLocation;
}
catch
{
$ok=$false;
write-host -ForegroundColor darkred "Failed to reach destination location $($destLocation)"
}
if ($ok)
{
try
{
# Load WinSCP .NET assembly
Add-Type -Path "WinSCPnet.dll"  # requires script co-located DLL
}
catch
{
$ok=$false;
write-host -ForegroundColor darkred "Failed to acquire types from the WinSCPnet.dll"
}
}
if ($ok)
{
try
{
# Setup session options
$sessionOptions = New-Object WinSCP.SessionOptions
$sessionOptions.Protocol = [WinSCP.Protocol]::Sftp
$sessionOptions.HostName = "sftp.SomeDomain.com"
$sessionOptions.UserName = "userID"
$sessionOptions.Password = 'Password'
$sessionOptions.SshHostKeyFingerprint = "ssh-rsa 1024 96:9b:ed:1f:66:8b:13:64:c3:ed:11:e0:27:68:62:67"
$session = New-Object WinSCP.Session
$session.Open($sessionOptions)
}
catch
{
$ok=$false;
write-host -ForegroundColor darkred "Failed to open SFTP connection"
}
}
if ($ok)
{
try #to get the directory listing
{
$directory = $session.ListDirectory($FTPDir)
}
catch
{
$ok=$false;
write-host -ForegroundColor darkred "Failed to get FTP Directory $($FTPDir)"
}
}
if ($ok)
{
try # to download each file that is not itself a directory
{
foreach ($f in $Directory.Files)
{
if (!$f.IsDirectory)
{
try
{
$RemotePath = "$($FTPDir)/$($f.name)"
$LocalPath  =  "$($DestLocation)$($f.name)"
$LocalPath  = $LocalPath.trim()
$session.GetFiles($remotePath, $localPath).Check()
write-host -ForegroundColor darkgreen "Deleted file from $($RemotePath) to $($LocalPath)"
}
catch
{
$ok=$false;
write-host -ForegroundColor darkred "Failed to download file from $($RemotePath) to $($LocalPath)"
}
}
}
}
catch
{
$ok=$false;
write-host -ForegroundColor darkred "Generic failure Failed to download file from FTP Directory $($FTPDir)"
}
}
if ($ok)
{
if ($DeleteSource)
{
foreach ($f in $Directory.Files)
{
if (!$f.IsDirectory)
{
try # try to delete each FTP file that is not a directory\
{
$RemotePath = "$($FTPDir)/$($f.name)"
$LocalPath  =  "$($DestLocation)$($f.name)"
$LocalPath  = $LocalPath.trim()
$session.RemoveFiles($remotePath).Check()
write-host -ForegroundColor darkgreen "Downloaded file from $($RemotePath) to $($LocalPath)"
}
catch
{
$ok=$false;
write-host -ForegroundColor darkred "Failed to download file from $($RemotePath) to $($LocalPath)"
}
}
}
}
}
0 replies

Leave a Reply

Want to join the discussion?
Feel free to contribute!

Leave a Reply

Your email address will not be published. Required fields are marked *