Migrating documents via SFTP

22

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)"
                }

            }
        }
    }
 }

Share this entry

Leave a Reply

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

Table of Contents

Categories

Categories