.netpowershellsftpwinscpwinscp-net

Pause between file uploads with WinSCP and PowerShell


I have below PowerShell script and I would really appreciate any help with this.

The script grabs files with filenames starting with COKA_*" from a network drive and uploads when to an SFTP site.

Problem: Destination site does not like to receive all files in batch but one at a time. Like 60 seconds delay between each file transfer.

Where can one add this delay within the script or iteration to push only one file at a time with a 60 seconds delay? I would really appreciate the help.

param (

    $localPath = "U:\####\COKA_*", # Source, one or more files generated at on a request
    $remotePath = "/from_/feast/Outbound/", #Destination file location
    $backupPath = "U:\####\Archive", # archive file destination
)

try
{
    # Load WinSCP .NET assembly
    Add-Type -Path "E:\######\WinSCP\WinSCPnet.dll"

    # Set up session options
    $sessionOptions = New-Object WinSCP.SessionOptions -Property @{
        Protocol = [WinSCP.Protocol]::Sftp
        HostName = "123.456.78.901"
        UserName = "iamencrypted"
        SshHostKeyFingerprint = "ssh-rsa 2048 DYPA3BjRCbKLosI5W9iamdefinatlydencrypted"
        SshPrivateKeyPath = "\\#####\###\###\##\FTP\######\#####\########.ppk"
    }

    $sessionOptions.AddRawSettings("AgentFwd", "1")

    $session = New-Object WinSCP.Session

    try
    {
        # Connect
        $session.Open($sessionOptions)

        # Upload files, collect results
        $transferResult = $session.PutFiles($localPath, $remotePath)

        # Iterate over every transfer
        foreach ($transfer in $transferResult.Transfers)
        {

            # Success or error?
            if ($transfer.Error -eq $Null)
            {
                Write-Host "Upload of $($transfer.FileName) succeeded, moving to Archive"
                # Upload succeeded, move source file to Archive
                Move-Item -force $transfer.FileName $backupPath
            }
            else
            {
                Write-Host "Upload of $($transfer.FileName) failed: $($transfer.Error.Message)"
            }
        }
    }
    finally
    {
        # Disconnect, clean up
        $session.Dispose()
    }

    exit 0
}
catch [Exception]
{
    Write-Host "Error: $($_.Exception.Message)"
    exit 1
}

Solution

  • Then you cannot use Session.PutFiles with a file mask.

    You have to find the files you want to upload yourself and then call Session.PutFiles (or even better Session.PutFileToDirectory) individually for each file with a pause between (Start-Sleep).

    Use Get-ChildItem for that.

    $files = Get-ChildItem $localPath
    
    foreach ($file in $files)
    {
        $localFilePath = $file.FullName
        $transferResult = $session.PutFileToDirectory($localFilePath, $remotePath)
    
        if ($transferResult.IsSuccess)
        {
            Write-Host "Upload of $localFilePath succeeded, moving to Archive"
            # Upload succeeded, move source file to Archive
            Move-Item -Force $localFilePath $backupPath
        }
        else
        {
            $err = $transferResult.Failures[0].Message
            Write-Host "Upload of $localFilePath failed: $err"
        }
    
        Start-Sleep -Seconds 60
    }